/* Axyra demo site — design tokens and layout, extracted from the prototype
   (prototype/Axyra Demo Pages.dc.html: Mock 1 = gallery, Mock 2 = detail). */

:root {
    --ax-accent: #50e3c2;
    --ax-accent-hover: #7ff0d8;
    --ax-accent-deep: #0b7561;
    --ax-amber: #f5b642;
    --ax-amber-deep: #a16207;

    --ax-dark-bg: #23222a;
    --ax-dark-header: #1b1b22;
    --ax-dark-card: #1a1a1a;
    --ax-dark-panel: #0e0e16;
    --ax-dark-thumb: #1e1e26;
    --ax-dark-cell: #2b2b36;
    --ax-dark-cell-mid: #2e5f57;
    --ax-dark-text: #e8e8ee;
    --ax-dark-dim: #a9a9b6;
    --ax-dark-muted: #9a9aa8;
    --ax-dark-border: rgba(255, 255, 255, .07);

    --ax-code-dim: #8f8fa0;
    --ax-code-fn: #c8c8d4;

    --ax-light-text: #111;
    --ax-light-body: #444;
    --ax-light-muted: #5a5a5a;
    --ax-light-border: rgba(0, 0, 0, .12);

    --ax-font: 'Ubuntu', 'Helvetica Neue', Helvetica, sans-serif;
    --ax-font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ZK ships `body{margin:0;padding:0 5px}` in zul/css/zk.wcs, and zkmax's
   tablet.css.dsp raises it to `padding:12px 16px`. The page ground is painted by
   .ax-gallery / .ax-detail, not by body, so any body padding leaves strips of the
   white html background down both edges — invisible on the light detail page,
   white bars on the dark gallery. axyra.css is the last stylesheet in the head,
   so resetting it here wins on order without needing !important. */
body {
    margin: 0;
    padding: 0;
    font-family: var(--ax-font);
}

/* Page switches. Between a page's HTML arriving and its widgets mounting, ZK
   covers the window with div.z-temp, which its theme paints grey. Right after the
   mount it may also raise its full-window "Processing..." mask (#zk_proc-m) for a
   few milliseconds, when the spreadsheet's first request overlaps the mount. On
   the white detail page both read as a flicker when moving from one demo to the
   next. The placeholder takes the page's own ground instead (index.zul marks the
   dark gallery with html.ax-dark-boot), and the busy box and its mask stay hidden
   for half a second, so a flash never shows while slow work still gets one. */
.z-temp {
    background: #fff;
}

html.ax-dark-boot .z-temp {
    background: var(--ax-dark-bg);
}

.z-temp .z-loading,
#zk_proc,
#zk_proc-m {
    animation: ax-busy-reveal 0s linear .5s both;
}

@keyframes ax-busy-reveal {
    from { visibility: hidden; }
    to { visibility: visible; }
}

/* The cookie banner. load-ga4.js (lang-addon.xml) inserts its HTML on every page
   load while gdpr.css, the stylesheet that hides it by default, is still on its
   way from zkoss.org, so the banner shows unstyled for a moment. Hiding it here,
   in a stylesheet already loaded, closes that gap: cookieManagement.js displays
   the banner with an inline display:block, which wins over this rule, and does
   so only while consent is still missing. */
#cookie-popup {
    display: none;
}

/* Shared 1200px container — every section on both pages uses it. content-box is
   deliberate: the mock sizes 1200px of *content* plus 32px gutters, and that extra
   64px is what lets the More demos grid fit four 280px columns instead of three. */
.ax-wrap {
    box-sizing: content-box;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 32px;
}

/* ===== Visited links =====

   A visited link must look exactly like an unvisited one. The browser's own
   a:visited rule is an element plus a pseudo-class, which outranks every
   single-class rule, so each link class restates its resting colour here.

   This block sits BEFORE the component sections on purpose. Every rule in it is
   two classes' worth of specificity, which already beats the UA's a:visited from
   anywhere in the file - but the :hover rules below are worth exactly the same,
   so whichever comes last wins. Kept at the end, as it used to be, a visited link
   ignored its own hover colour: that is the classic reason for ordering link
   rules link-visited-hover-active, and it is what this placement restores. */

.ax-card:visited,
.ax-feature-card:visited,
.ax-wordmark:visited {
    color: inherit;
}

/* A description link keeps its own resting colour once visited, rather than the
   browser purple, for the same reason as the rules above. */
.ax-desc-body a:visited {
    color: var(--ax-accent-deep);
}

.ax-card-title:visited {
    color: #fff;
}

.ax-nav-link:visited {
    color: #fff;
}

.ax-drawer-back:visited {
    color: var(--ax-dark-text);
}

/* The drawer lists every demo, so after a browse most of it is visited — these
   were the ones still turning purple. The active entry is restated after the
   plain one because both selectors are 0,2,0 and order is what settles it. */
.ax-drawer-link:visited {
    color: var(--ax-dark-dim);
}

.ax-drawer-link--active:visited {
    color: var(--ax-accent);
}

.ax-nav-link-light:visited {
    color: #1a1a1a;
}

.ax-btn-outline:visited {
    color: var(--ax-accent);
}

.ax-btn-outline-deep:visited {
    color: var(--ax-accent-deep);
}

/* ===== Header (shared by both pages, dark or light) ===== */

/* Both headers now carry the same box, taken from test.keikai.io/axyra's
   .smallheader - see the note on .ax-header--light below for what was and was not
   copied. Only the ground colour differs: the gallery keeps its own dark tone
   rather than their #202020, and the detail page keeps white. */
.ax-header--dark {
    background: var(--ax-dark-header);
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 56px;
    z-index: 40;
    text-align: center;
    text-decoration: none;
    font-family: 'Cabin', sans-serif;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .66);
    transition: background-color .5s, box-shadow .5s;
}

/* Style parity with the header on test.keikai.io/axyra, i.e. its
   `<div id="header" class="smallheader axyra-header">`. Everything here is lifted
   from that page's .smallheader rule except the two the brief held back:
   background-color stays #fff (theirs is #202020) and the text colours stay ours.
   Their rule carries no border - the shadow alone separates the bar from the page
   - so the old border-bottom goes with it.

   z-index is the single number deliberately NOT copied. Theirs is 500, but that
   page has no drawer; this one puts a drawer at 60 over a backdrop at 50, and 500
   would paint the header on top of both. 40 matches .ax-header--dark and keeps
   the header under the drawer, which is invisible to parity either way. */
.ax-header--light {
    background: #fff;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 56px;
    z-index: 40;
    text-align: center;
    text-decoration: none;
    font-family: 'Cabin', sans-serif;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .66);
    transition: background-color .5s, box-shadow .5s;
}

/* Their logo and nav are position:absolute against the viewport edges, stepping
   through a set of insets by breakpoint, rather than sitting in a centred
   container. --ax-hdr-inset carries that step so the logo's left, the nav's right
   and the hamburger's gutter all move together; --ax-hdr-link-pad carries their
   #headercontent a padding-left, which is how that nav spaces its links.

   Their base rules are left:5% / right:5% / padding-left:75px, but every viewport
   is covered by a breakpoint below, so the 5% never actually applies and is not
   reproduced here. */
.ax-header--dark,
.ax-header--light {
    --ax-hdr-inset: 23px;
    --ax-hdr-link-pad: 25px;
}

@media (min-width: 768px) {
    .ax-header--dark,
    .ax-header--light {
        --ax-hdr-inset: 30px;
        --ax-hdr-link-pad: 30px;
    }
}

@media (min-width: 960px) {
    .ax-header--dark,
    .ax-header--light {
        --ax-hdr-inset: 48px;
        --ax-hdr-link-pad: 36px;
    }
}

@media (min-width: 1440px) {
    .ax-header--dark,
    .ax-header--light {
        --ax-hdr-inset: 72px;
    }
}

/* Their bar is 56px tall; this one was 64px. The centred 1200px wrapper is what
   held the logo ~100px off the screen edge, so it no longer constrains anything -
   every child anchors to a screen edge instead. */
.ax-header-inner {
    display: flex;
    align-items: center;
    box-sizing: content-box;
    margin: 0 auto;
    padding: 0;
    height: 56px;
}

/* Their page has no hamburger, so there is nothing to copy for it. The whole left
   group is anchored 32px back from the inset - the hamburger's own 20px plus the
   12px gap - so the logo lands on --ax-hdr-inset and the button sits in the gutter
   beside it. The 6px floor keeps the button on screen at the narrow breakpoints,
   where the gutter is shallower than 32px; there the logo sits a few px inside the
   inset rather than on it, which is the only place the extra button costs any
   parity. */
.ax-header-left {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: none;
    position: absolute;
    left: max(6px, calc(var(--ax-hdr-inset) - 32px));
    top: 0;
    height: 56px;
}

/* The gap sets the bar pitch, and the pitch is what keeps the three bars looking
   alike at fractional browser zoom. Each bar rasterises at its own subpixel offset,
   so unless pitch x zoom is a whole number of device pixels one bar lands on a half
   and smears across an extra row while its neighbours stay crisp. At the old 4px
   gap the pitch was 6px, which at 125% put the bars at 0 / 7.5 / 15 device px and
   painted the middle one 4 rows tall against 3 for the outer pair (5/4/5 at 175%).
   A 6px gap makes the pitch 8px, so every quarter-step zoom - 125, 150, 175, 200% -
   lands exactly and all three bars match. */
.ax-hamburger {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 20px;
    flex: none;
    padding: 0;
    background: transparent;
    border: 0;
    cursor: pointer;
}

.ax-hamburger:hover {
    opacity: .7;
}

.ax-hamburger-bar {
    display: block;
    height: 2px;
}

.ax-header--dark .ax-hamburger-bar {
    background: var(--ax-dark-text);
}

.ax-header--light .ax-hamburger-bar {
    background: var(--ax-light-text);
}

/* #headerlogo from their page, as .axyra-header restyles it: Ubuntu 500 at 24px
   on a 56px line, against our old 700 at 22px. Colours are untouched, and their
   logo sets no letter-spacing. Horizontal anchoring comes from .ax-header-left
   above; the 56px line box does the vertical centring, as theirs does. */
.ax-wordmark {
    font-family: var(--ax-font);
    font-weight: 500;
    font-size: 24px;
    line-height: 56px;
    letter-spacing: normal;
    vertical-align: middle;
    text-decoration: none;
}

.ax-header--dark .ax-wordmark {
    color: #fff;
}

.ax-header--light .ax-wordmark {
    color: var(--ax-light-text);
}

/* The group gap is 12px so the logo lands on the inset, but this sat 28px clear
   of the wordmark before and should still. */
.ax-header-tagline {
    /* Flex centring aligns em boxes, which puts this label dead on "Axyra"'s
       cap-height centre - measured, both at 27.60. But the eye reads the logo's
       mass down to the descender of the y, whose full-ink centre is 29.80, so an
       optically centred label has to follow it. Hence the 2px. */
    position: relative;
    top: 2px;
    margin-left: 16px;
    font-size: 12px;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ax-dark-muted);
}

/* #headercontent: absolute against the right edge on the same inset, 16px/500 on
   a 56px line, links spaced by padding-left rather than a flex gap. Link colours
   are left alone. */
.ax-nav {
    display: flex;
    align-items: center;
    gap: 0;
    font-size: 16px;
    font-weight: 500;
    line-height: 56px;
    position: absolute;
    right: var(--ax-hdr-inset);
    top: 0;
    margin-left: 0;
}

/* font:inherit is what carries Cabin down from the bar. ZK renders these as
   <a class="z-a"> and .z-a sets its own font-family; nothing of ours competed with
   it, so the family alone stayed on the theme's Helvetica while the size and
   weight we do set came through. Their #headercontent a inherits everything from
   the bar, so inheriting the whole font is the faithful copy. */
.ax-nav-link,
.ax-nav-link-light {
    font: inherit;
    padding-left: var(--ax-hdr-link-pad);
    cursor: pointer;
}

/* ZK wraps a <span>'s text in <span class="z-label">, which carries the theme's
   16px/400 Helvetica and overrides whatever the element around it sets. That is
   why the gallery wordmark rendered small while the detail page's did not: this
   one is <span>Axyra</span>, that one is <a label="Axyra"> whose text sits
   directly in the anchor. Same for the tagline beside it. */
.ax-header--dark .z-label,
.ax-header--light .z-label {
    font: inherit;
    color: inherit;
}

/* "Keikai", set off from the product links by a faint bar, as in the keikai.io
   site header. The bar is drawn in the link's own colour so it reads on both the
   dark and the light header, and it is not part of the click target. */
.ax-nav .ax-nav-divider {
    margin-left: 14px;
}

.ax-nav .ax-nav-divider::before {
    content: "|";
    display: inline-block;
    margin-right: var(--ax-hdr-link-pad);
    opacity: .35;
    pointer-events: none;
}

/* The site's narrow-screen steps: Contact goes first, then the divider tightens,
   then Demo goes, so Quickstart and Keikai always fit beside the wordmark. */
@media (max-width: 599px) {
    .ax-nav .ax-nav-contact {
        display: none;
    }
}

@media (max-width: 479px) {
    .ax-nav .ax-nav-divider {
        margin-left: 0;
    }

    .ax-nav .ax-nav-divider::before {
        margin-right: 14px;
    }
}

@media (max-width: 399px) {
    .ax-nav .ax-nav-demo {
        display: none;
    }
}

/* Their widest breakpoint nudges the nav up a size and onto a 57px line. */
@media (min-width: 1440px) {
    .ax-nav {
        font-size: 20px;
        line-height: 57px;
    }
}

/* Header links, dark bar: white at rest, grey on hover. The interactive states
   spell out text-decoration because ZK renders these as <a class="z-a"> and
   underlines them on hover - a two-class selector that outranks the rule above,
   so setting it once on .ax-nav-link is not enough to keep them clean. */
.ax-nav-link {
    color: #fff;
    text-decoration: none;
}

.ax-nav-link:hover,
.ax-nav-link:focus,
.ax-nav-link:active {
    color: #a6a6a6;
    text-decoration: none;
}

.ax-nav-link--active {
    color: var(--ax-accent);
}

/* Header links, white bar: near-black at rest, mid grey on hover. The old rule
   underlined on hover deliberately; the brief drops that. */
.ax-nav-link-light {
    color: #1a1a1a;
    text-decoration: none;
}

.ax-nav-link-light:hover,
.ax-nav-link-light:focus,
.ax-nav-link-light:active {
    color: #5c5c5c;
    text-decoration: none;
}

/* ===== Buttons ===== */

.ax-btn {
    display: inline-flex;
    box-shadow: none;
    align-items: center;
    gap: 10px;
    padding: 12px 20px;
    border-radius: 6px;
    border: 1px solid transparent;
    background: none;
    font-family: var(--ax-font);
    font-size: 15px;
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
}

.ax-btn-outline {
    padding: 11px 20px;
    border-color: rgba(80, 227, 194, .5);
    color: var(--ax-accent);
}

.ax-btn-outline-deep {
    border-color: rgba(11, 117, 97, .45);
    color: var(--ax-accent-deep);
}

/* ===== Gallery (index.zul) ===== */

.ax-gallery {
    min-height: 100vh;
    /* The header is position:fixed for parity, so it no longer takes up flow
       space. This gives back the 56px it covers. */
    padding-top: 56px;
    padding-bottom: 72px;
    background: var(--ax-dark-bg);
    color: var(--ax-dark-text);
    font-family: var(--ax-font);
}

.ax-hero {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: 56px;
    align-items: start;
    padding-top: 64px;
    padding-bottom: 40px;
}

.ax-hero-eyebrow {
    font-family: var(--ax-font-mono);
    font-size: 12px;
    letter-spacing: .2em;
    color: var(--ax-accent);
    margin-bottom: 18px;
}

.ax-hero-title {
    margin: 0;
    font-weight: 700;
    font-size: 40px;
    line-height: 1.2;
    color: #fff;
    text-wrap: pretty;
}

.ax-hero-copy-col {
    padding-top: 8px;
}

.ax-hero-copy {
    margin: 0 0 22px;
    font-size: 16px;
    line-height: 1.65;
    color: var(--ax-dark-dim);
    text-wrap: pretty;
}

.ax-section-head {
    display: flex;
    align-items: baseline;
    padding-bottom: 14px;
    border-bottom: 1px solid rgba(255, 255, 255, .1);
    margin-top: 64px;
}

.ax-section-head:first-child {
    margin-top: 8px;
}

.ax-section-title {
    margin: 0;
    font-weight: 500;
    font-size: 24px;
    color: #fff;
}

/* ZK renders <label> as <span class="z-label"> carrying the theme's own 16px/400
   Helvetica, and that beats anything the heading sets, because the heading only
   styles the ancestor. The forEach section headings pass their title through a
   <label>, while the "More demos" heading is literal text in the <h2> - which is
   the whole reason only that one looked right. Forcing inheritance makes every
   section heading render identically, and gives the counts beside them the mono
   face .ax-section-count already asks for. */
.ax-section-title .z-label,
.ax-section-count .z-label {
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
}

.ax-section-count {
    margin-left: auto;
    font-family: var(--ax-font-mono);
    font-size: 12px;
    letter-spacing: .18em;
    color: var(--ax-dark-muted);
}

/* Fixed 3 columns per the handoff, rather than an auto-fit track: the nine
   featured cards are meant to read as three rows of three at the 1200px measure. */
.ax-feature-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
    margin-top: 32px;
}

.ax-feature-card {
    display: flex;
    flex-direction: column;
    background: var(--ax-dark-card);
    border: 1px solid var(--ax-dark-border);
    border-radius: 8px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
}

.ax-feature-body {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 18px 20px 22px;
}

/* Meta grey, not amber. The handoff assigns this value to monospace eyebrows and
   reserves amber for the 8px dot beside "Featured", which this gallery no longer
   draws - so the amber here was a leftover. It also read almost as loud as the
   title it introduces: 9.66:1 against the card against the title's own 17.40:1,
   and only 1.80:1 against the title itself. At 6.27:1 / 2.78:1 the eyebrow now
   sits under the heading instead of competing with it, and matches
   .ax-card-category on the compact cards below. */
.ax-feature-category {
    font-family: var(--ax-font-mono);
    font-size: 11px;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ax-dark-muted);
}

.ax-feature-title {
    font-family: var(--ax-font);
    font-weight: 700;
    font-size: 18px;
    color: #fff;
    text-decoration: none;
}

.ax-feature-card:hover .ax-feature-title {
    color: var(--ax-accent);
}

/* Featured thumbnails — CSS-drawn abstract shapes, no images. */

/* Card thumbnails. The restyled art is 726x300; the older pieces are still 880x300,
   so the two sets have different aspect ratios and object-fit:cover is what keeps
   them interchangeable — the wider originals lose a little width, the newer ones a
   little height. Keep new art 300px tall and cover does the rest. */
.ax-thumb-img,
.ax-thumb-img > img {
    display: block;
    width: 100%;
    height: 150px;
    object-fit: cover;
    background: var(--ax-dark-thumb);
}

.ax-thumb {
    height: 150px;
    background: var(--ax-dark-thumb);
}

.ax-thumb > .z-html {
    display: contents;
}

.ax-thumb--grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    grid-template-rows: repeat(5, 1fr);
    gap: 2px;
    padding: 16px;
}

.ax-thumb-cell {
    background: var(--ax-dark-cell);
}

.ax-thumb-cell--mid {
    background: var(--ax-dark-cell-mid);
}

.ax-thumb-cell--on {
    background: var(--ax-accent);
    opacity: .85;
}

.ax-thumb--rows {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 11px;
    padding: 16px 20px;
}

.ax-thumb-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.ax-thumb-row-label {
    flex: none;
    width: 56px;
    height: 9px;
    background: var(--ax-dark-cell);
}

.ax-thumb-row-bar {
    flex: 1;
    height: 9px;
    background: var(--ax-dark-cell);
}

.ax-thumb-row-bar--1 {
    background: linear-gradient(90deg, var(--ax-accent) 62%, var(--ax-dark-cell) 62%);
}

.ax-thumb-row-bar--2 {
    background: linear-gradient(90deg, var(--ax-dark-cell-mid) 88%, var(--ax-dark-cell) 88%);
}

.ax-thumb-row-bar--3 {
    background: linear-gradient(90deg, var(--ax-dark-cell-mid) 34%, var(--ax-dark-cell) 34%);
}

.ax-thumb-row-bar--4 {
    background: linear-gradient(90deg, var(--ax-dark-cell-mid) 55%, var(--ax-dark-cell) 55%);
}

.ax-thumb--bars {
    display: flex;
    align-items: flex-end;
    gap: 9px;
    padding: 20px;
}

.ax-thumb-bar {
    flex: 1;
    background: var(--ax-dark-cell);
}

.ax-thumb-bar--1 { height: 38%; background: var(--ax-dark-cell); }
.ax-thumb-bar--2 { height: 66%; background: var(--ax-dark-cell-mid); }
.ax-thumb-bar--3 { height: 48%; background: var(--ax-dark-cell); }
.ax-thumb-bar--4 { height: 88%; background: var(--ax-accent); }
.ax-thumb-bar--5 { height: 58%; background: var(--ax-dark-cell-mid); }
.ax-thumb-bar--6 { height: 30%; background: var(--ax-dark-cell); }
.ax-thumb-bar--7 { height: 72%; background: var(--ax-dark-cell-mid); }

/* Four fixed columns for the compact cards, per the handoff. At the 1200px
   measure that is a 288px track, which is why the snippet below wraps instead of
   clipping the way it did in the old 280px-minimum auto-fit layout. */
.ax-card-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 16px;
    margin-top: 28px;
}

.ax-card {
    display: flex;
    flex-direction: column;
    background: var(--ax-dark-thumb);
    border: 1px solid rgba(255, 255, 255, .05);
    border-radius: 6px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
}

.ax-card--soon {
    opacity: .7;
    cursor: default;
}

.ax-card--more {
    background: transparent;
    border: 1px dashed rgba(255, 255, 255, .14);
}

.ax-card-body {
    display: flex;
    flex-direction: column;
    gap: 5px;
    flex: 1;
    padding: 16px 18px 0;
}

.ax-card-category {
    font-family: var(--ax-font-mono);
    font-size: 10px;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ax-dark-muted);
}

.ax-card-title {
    font-family: var(--ax-font);
    font-weight: 500;
    font-size: 16px;
    color: var(--ax-dark-text);
    text-decoration: none;
}

.ax-card:hover .ax-card-title {
    color: var(--ax-accent);
}

/* Must come after .ax-card:hover .ax-card-title (same specificity) to still win on soon cards. */
.ax-card--soon .ax-card-title,
.ax-card--soon .ax-card-title:hover {
    color: var(--ax-dark-muted);
}

.ax-card-snippet {
    margin-top: 14px;
    padding: 10px 18px;
    border-top: 1px solid rgba(255, 255, 255, .05);
    font-family: var(--ax-font-mono);
    font-size: 11px;
    line-height: 1.7;
    color: var(--ax-dark-muted);
    overflow-wrap: anywhere;
}

/* The method name inside a card snippet, brightened out of the dim surrounding call.
   GalleryViewModel.snippetHtml() emits the span. */
.ax-card-snippet-fn {
    color: var(--ax-code-fn);
}

/* ===== Drawer (shared by both pages) ===== */

.ax-backdrop {
    position: fixed;
    inset: 0;
    z-index: 50;
    background: rgba(0, 0, 0, .6);
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
}

.ax-drawer {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 320px;
    z-index: 60;
    display: flex;
    flex-direction: column;
    background: var(--ax-dark-bg);
    border-right: 1px solid var(--ax-dark-border);
    transform: translateX(-100%);
    /* visibility is delayed on the way out so the slide-out animation still plays, then the
       panel (and its links/close button) leaves the tab order while off-screen. */
    visibility: hidden;
    transition: transform .24s ease, visibility 0s linear .24s;
}

body.ax-drawer-open .ax-backdrop {
    opacity: 1;
    pointer-events: auto;
}

body.ax-drawer-open .ax-drawer {
    transform: translateX(0);
    visibility: visible;
    transition: transform .24s ease;
}

.ax-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    border-bottom: 1px solid var(--ax-dark-border);
}

.ax-drawer-title {
    font-size: 20px;
    font-weight: 700;
    color: var(--ax-accent);
}

/* A fixed 32px box is not enough to centre the glyph: this is a ZK <button>, so
   it arrives with the theme's own padding and line-height, which push the cross
   off-centre inside that box. Centring it as a flex container and zeroing both
   is what actually places it, whatever the theme sets. */
.ax-drawer-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
    color: var(--ax-dark-text);
    font-size: 20px;
    line-height: 1;
    text-align: center;
    cursor: pointer;
}

/* The base rule's transparent background is not enough on its own: this is a ZK
   <button>, and .z-button:hover / :active are two-class selectors that outrank a
   single-class rule, so the theme repaints its own fill on those states. They have
   to be restated here - the same reason .ax-tab spells all three out. Only the ink
   changes on hover; the button never grows a background. */
.ax-drawer-close:hover,
.ax-drawer-close:focus,
.ax-drawer-close:active {
    background: transparent;
    border: 0;
    box-shadow: none;
    color: var(--ax-accent);
}

.ax-drawer-body {
    overflow: auto;
    padding: 20px 0 40px;
}

/* One heading per gallery section, title left and count right. */
.ax-drawer-heading {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 0 24px 10px;
    font-size: 16px;
    font-weight: 700;
    color: var(--ax-dark-text);
}

/* Only sections after the first need air above them: the first one sits directly
   under the drawer head, which brings its own padding. */
.ax-drawer-nav + .ax-drawer-heading {
    margin-top: 24px;
}

.ax-drawer-count {
    font-family: var(--ax-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: .18em;
    color: var(--ax-dark-muted);
}

/* ZK wraps a <label>'s text in <span class="z-label">, which carries the theme's
   own 16px/400 Helvetica and would override the heading around it - the same
   thing that made the gallery's section titles render small. */
.ax-drawer-heading .z-label,
.ax-drawer-count .z-label {
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
}

.ax-drawer-nav {
    display: flex;
    flex-direction: column;
}

.ax-drawer-link {
    display: block;
    padding: 8px 24px 8px 40px;
    font-size: 14px;
    font-weight: 600;
    color: var(--ax-dark-dim);
    text-decoration: none;
}

.ax-drawer-link:hover {
    color: var(--ax-accent);
    background: var(--ax-dark-card);
}

.ax-drawer-link--active {
    color: var(--ax-accent);
    border-left: 3px solid var(--ax-accent);
    background: var(--ax-dark-card);
}

.ax-drawer-foot {
    margin: 26px 24px 0;
    padding-top: 20px;
    border-top: 1px solid var(--ax-dark-border);
}

.ax-drawer-back {
    font-size: 14px;
    font-weight: 700;
    color: var(--ax-dark-text);
    text-decoration: none;
}

.ax-drawer-back:hover {
    color: var(--ax-accent);
}

/* ===== Detail page (demo.zul) ===== */

.ax-detail {
    min-height: 100vh;
    /* The light header is position:fixed to match test.keikai.io/axyra, so it no
       longer takes up flow space. This gives back the 56px it covers. */
    padding-top: 56px;
    background: #fff;
    color: var(--ax-light-text);
    font-family: var(--ax-font);
}

.ax-detail-title-block {
    padding-top: 52px;
}

.ax-detail-title-row {
    display: flex;
    align-items: baseline;
    gap: 14px;
    flex-wrap: wrap;
}

.ax-detail-h1 {
    margin: 0;
    font-weight: 700;
    font-size: 34px;
    color: var(--ax-light-text);
}

.ax-detail-category {
    font-family: var(--ax-font-mono);
    font-size: 12px;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ax-amber-deep);
}

.ax-detail-desc {
    display: block;
    margin: 14px 0 0;
    font-size: 16px;
    line-height: 1.65;
    color: var(--ax-light-body);
    text-wrap: pretty;
}

.ax-tabbar {
    display: inline-flex;
    gap: 30px;
    margin-top: 34px;
    border-bottom: 1px solid var(--ax-light-border);
}

.ax-tab {
    padding: 0 2px 12px;
    box-shadow: none;
    margin-bottom: -1px;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    /* These are ZK <button>s, so they arrive with border-radius on all four
       corners from the theme's --zk-input-border-radius. On the bottom edge that
       rounds off the ends of .ax-tab--active's 2px accent underline, which should
       read as a flat rule under the label. The top corners are left alone -
       nothing paints there, so the radius is invisible. */
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    font-family: var(--ax-font);
    font-size: 15px;
    color: var(--ax-light-muted);
    cursor: pointer;
}

.ax-tab--active {
    font-weight: 700;
    color: var(--ax-accent-deep);
    border-bottom-color: var(--ax-accent-deep);
}

.ax-main {
    display: flex;
    flex-direction: column;
    padding-bottom: 72px;
}

.ax-rule-row {
    display: flex;
    align-items: center;
    gap: 20px;
    margin-top: 36px;
}

.ax-rule-row--result {
    margin-top: 44px;
}

.ax-rule-label {
    font-family: var(--ax-font-mono);
    font-size: 12px;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--ax-accent-deep);
}

.ax-rule-line {
    flex: 1;
    height: 1px;
    background: var(--ax-light-border);
}

.ax-rule-caption {
    font-size: 13px;
    color: var(--ax-light-muted);
}

/* Source / code panel */

.ax-code-panel {
    margin-top: 18px;
    background: var(--ax-dark-panel);
    border: 1px solid var(--ax-dark-border);
    border-radius: 8px;
    overflow: hidden;
}

.ax-code-tabbar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--ax-dark-border);
}

.ax-code-filetabs {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    overflow: auto;
}

.ax-file-tab {
    padding: 5px 10px;
    box-shadow: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 4px;
    font-family: var(--ax-font-mono);
    font-size: 12px;
    color: var(--ax-dark-muted);
    white-space: nowrap;
    cursor: pointer;
}

/* The sample currently in the code panel. Mint on the dark ground is the same
   accent pair .ax-btn-outline uses there: a .12 tint behind a legible border. The
   old grey lift was almost invisible against --ax-dark-panel. */
.ax-file-tab--active {
    background: rgba(80, 227, 194, .12);
    border-color: rgba(80, 227, 194, .45);
    color: var(--ax-accent);
}

.ax-code-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

.ax-code-btn {
    padding: 6px 12px;
    box-shadow: none;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .14);
    border-radius: 4px;
    font-family: var(--ax-font-mono);
    font-size: 11px;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ax-dark-dim);
    cursor: pointer;
}

.ax-code-btn--copy {
    border-color: rgba(80, 227, 194, .4);
    color: var(--ax-accent);
}

/* Every tab and button on these pages is a ZK <button>, and ZK's .z-button:hover,
   :focus and :active each repaint colour, border-color and background-color from the
   theme's primary palette — states the mock has no equivalent for. Those rules are one
   class plus a pseudo-class, so a plain .ax-* rule loses to them; each control has to
   spell its own states out. Keyboard focus gets a ring rather than a fill. */
.ax-tab:hover,
.ax-tab:focus,
.ax-tab:active {
    background: none;
    border-bottom-color: transparent;
    color: var(--ax-light-text);
}

.ax-tab--active:hover,
.ax-tab--active:focus,
.ax-tab--active:active {
    background: none;
    border-bottom-color: var(--ax-accent-deep);
    color: var(--ax-accent-deep);
}

.ax-file-tab:hover,
.ax-file-tab:focus,
.ax-file-tab:active {
    background: none;
    border-color: transparent;
    color: var(--ax-dark-text);
}

.ax-file-tab--active:hover,
.ax-file-tab--active:focus,
.ax-file-tab--active:active {
    background: rgba(80, 227, 194, .12);
    border-color: rgba(80, 227, 194, .8);
    color: var(--ax-accent);
}

.ax-code-btn:hover,
.ax-code-btn:focus,
.ax-code-btn:active {
    background: none;
    border-color: var(--ax-accent);
    color: var(--ax-accent);
}

.ax-btn-outline:hover,
.ax-btn-outline:focus,
.ax-btn-outline:active {
    background: rgba(80, 227, 194, .12);
    border-color: rgba(80, 227, 194, .8);
    color: var(--ax-accent);
    text-decoration: none;
}

.ax-btn-outline-deep:hover,
.ax-btn-outline-deep:focus,
.ax-btn-outline-deep:active {
    background: rgba(11, 117, 97, .08);
    border-color: rgba(11, 117, 97, .8);
    color: var(--ax-accent-deep);
    text-decoration: none;
}

.ax-btn:focus-visible,
.ax-tab:focus-visible,
.ax-file-tab:focus-visible,
.ax-code-btn:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

.ax-code-body {
    display: block;
    padding: 20px 22px;
    max-height: 360px;
    overflow-x: auto;
    overflow-y: auto;
    font-family: var(--ax-font-mono);
    font-size: 13px;
    line-height: 1.85;
    color: var(--ax-code-fn);
    transition: max-height .2s ease;
}

.ax-code-body--collapsed {
    padding-top: 0;
    padding-bottom: 0;
    max-height: 0;
    overflow: hidden;
}

.ax-code-pre {
    margin: 0;
}

/* highlight.js output (loaded from cdnjs) — structural overrides only, the
   token colours come from the highlight.js theme linked in demo.zul. */

.ax-code-body .hljs {
    background: transparent;
    padding: 0;
}

.ax-code-body table.hljs-ln {
    border-collapse: collapse;
    width: 100%;
}

.ax-code-body .hljs-ln-numbers {
    width: 1%;
    padding-right: 16px;
    text-align: right;
    vertical-align: top;
    color: #7e7e90;
    user-select: none;
    border: 0;
}

.ax-code-body .hljs-ln-n:before {
    content: attr(data-line-number);
}

.ax-code-body .hljs-ln-code {
    padding-left: 12px;
    vertical-align: top;
    border: 0;
}

/* Result panel */

/* highlight.js token palette, taken from the mock's inline spans rather than a CDN
   theme — atom-one-dark's salmon tags and orange attributes are not the mock's. */
.ax-code-body .hljs {
    background: transparent;
    color: var(--ax-code-fn);
}

.ax-code-body .hljs-tag,
.ax-code-body .hljs-name,
.ax-code-body .hljs-keyword {
    color: var(--ax-accent);
}

.ax-code-body .hljs-attr,
.ax-code-body .hljs-type,
.ax-code-body .hljs-title.class_ {
    color: #9d9dff;
}

.ax-code-body .hljs-string,
.ax-code-body .hljs-number,
.ax-code-body .hljs-literal {
    color: #d8b070;
}

.ax-code-body .hljs-comment,
.ax-code-body .hljs-meta {
    color: var(--ax-dark-muted);
}

.ax-code-body .hljs-title.function_ {
    color: var(--ax-code-fn);
}

.ax-result-panel {
    margin-top: 18px;
    background: #fff;
    border: 1px solid var(--ax-light-border);
    border-radius: 8px;
    overflow: hidden;
}

.ax-result-body {
    display: flex;
    flex-direction: column;
    height: 420px;
    overflow: hidden;
    background: #fff;
}

.ax-next-row {
    display: flex;
    justify-content: flex-end;
    margin-top: 36px;
}

.ax-next-btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.ax-next-kicker {
    font-family: var(--ax-font-mono);
    font-size: 11px;
    letter-spacing: .18em;
    font-weight: 400;
    color: var(--ax-light-muted);
}

/* Description tab */

/* No measure of its own: the description fills the 1200px .ax-wrap, so its text starts
   and ends on the same gutter as the title, the tab bar and the demo panel above it. */
.ax-desc-main {
    padding: 48px 0 72px;
}

.ax-desc-body {
    font-size: 17px;
    line-height: 1.6;
    color: var(--ax-light-text);
}

.ax-desc-body p {
    margin: 0 0 20px;
}

/* Links inside a description. Underlined, unlike the header nav: in a paragraph
   of prose the underline is the only thing marking the link, and these point off
   the site to the documentation. */
.ax-desc-body a,
.ax-desc-body a:link {
    color: var(--ax-accent-deep);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.ax-desc-body a:hover,
.ax-desc-body a:focus,
.ax-desc-body a:active {
    color: var(--ax-light-text);
    text-decoration: underline;
}

/* Inline code and sheet content in a description: API names, cell and column
   references, formula functions and template placeholders. Sized in em so it tracks
   the 17px prose, and held on one line so a reference like B6*C6 never breaks in two. */
.ax-desc-body code {
    font-family: var(--ax-font-mono);
    font-size: .88em;
    padding: 2px 6px;
    border: 1px solid var(--ax-light-border);
    border-radius: 4px;
    background: rgba(0, 0, 0, .035);
    color: var(--ax-light-text);
    white-space: nowrap;
}

/* ===== Session timeout banner =====

   Injected by the timeout-message script in WEB-INF/zk.xml (adapted from the ZK
   live demo's _timeout.css). It starts hidden because the script reveals it with
   slideDown. Fixed rather than absolute, so a reader scrolled down the gallery
   still sees it. It sits above the drawer (z-index 60) and Keikai's popups. */
#z-timeout {
    display: none;
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100000;
    box-sizing: border-box;
    width: 340px;
    max-width: calc(100vw - 32px);
    padding: 12px 16px;
    border: 1px solid var(--ax-accent-deep);
    border-radius: 8px;
    background: var(--ax-dark-header);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
    overflow: hidden;
}

#z-timeout span {
    display: block;
    font-family: var(--ax-font);
    font-size: 14px;
    line-height: 1.4;
    text-align: center;
    color: var(--ax-dark-text);
}

#z-timeout b {
    color: var(--ax-accent);
}

#z-timeout img {
    margin-left: 10px;
    vertical-align: middle;
}

/* ===== Mobile ===== */

@media (max-width: 760px) {
    .ax-hero {
        grid-template-columns: 1fr;
        gap: 32px;
        padding-top: 40px;
        padding-bottom: 32px;
    }

    .ax-hero-copy-col {
        padding-top: 0;
    }

    /* The tagline would collide with the nav links on a phone-width bar; the
       wordmark alone carries the brand there. */
    .ax-header-tagline {
        display: none;
    }

    /* One card per row: at phone width the fixed three- and four-column tracks
       squeeze each card below the width its thumbnail and snippet need. */
    .ax-feature-grid,
    .ax-card-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Copy and collapse are desktop affordances. Source on the clipboard is of
       little use on a phone mid-demo, and the pair crowd a tab strip that is
       already tight at this width. Hiding the buttons leaves .ax-code-actions
       empty, which costs no space - its gap only applies between items - so the
       file tabs get the whole bar. */
    .ax-code-btn {
        display: none;
    }
}

/* ===== Demo controls (demoimpl.zul) =====

   The button bar above each live demo. demoimpl.zul stacks two rows inside the
   result panel: #demoHeader holds the caption and the buttons, #demoContent the
   viewer that fills the rest. The buttons are ZK <button>s, so they arrive wearing
   .z-button from the theme; axyra.css is the last stylesheet in the head, so a
   matching single-class rule wins on order. The :hover/:focus/:active states have
   to be spelled out for the same reason as .ax-tab above — ZK repaints all three
   from its primary palette. */

.ax-result-body-content .ax-demo-header {
    box-sizing: border-box;
    padding: 10px 12px;
    border-bottom: 1px solid var(--ax-light-border);
    background: #fbfbfb;
}

/* The caption, then the buttons, on one line. The row wraps rather than scrolling
   or squeezing: a demo carries at most five buttons and the longest labels run to
   ~27 characters, which stops fitting the panel on a narrow window. */
.ax-result-body-content .ax-demo-menu {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.ax-demo-caption {
    flex: 0 0 auto;
    margin-right: 4px;
    white-space: nowrap;
    font-family: var(--ax-font);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ax-light-muted);
}

.ax-demo-btn {
    display: inline-block;
    flex: 0 0 auto;
    box-sizing: border-box;
    margin: 0;
    padding: 10px 14px;
    border: 1px solid rgba(11, 117, 97, .45);
    border-radius: 6px;
    background: #fff;
    box-shadow: none;
    font-family: var(--ax-font);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.3;
    text-align: center;
    white-space: nowrap;
    color: var(--ax-accent-deep);
    cursor: pointer;
}

.ax-demo-btn:hover,
.ax-demo-btn:focus,
.ax-demo-btn:active {
    background: rgba(11, 117, 97, .08);
    border-color: rgba(11, 117, 97, .8);
    color: var(--ax-accent-deep);
}

/* The demo currently showing in the result panel, marked by a flat accent-deep
   fill under a white label. The colour that used to draw the selected button's
   bottom edge now fills the whole control, so the signal reads from across the
   row instead of asking the eye to find a 4px edge.

   Carrying it in the fill also keeps every button the same size in every state:
   the old rule thickened one border and clawed the 3px back out of the padding,
   which held the label still but left the selected button a hair taller than its
   neighbours. There is no geometry left to compensate for. The border colour
   matches the fill so the 1px box stays, and white on #0b7561 is 5.7:1, past AA
   for this 14px bold label. The states are repeated because ZK's .z-button:hover
   would otherwise win. */
.ax-demo-btn--active,
.ax-demo-btn--active:hover,
.ax-demo-btn--active:focus,
.ax-demo-btn--active:active {
    background: var(--ax-accent-deep);
    border-color: var(--ax-accent-deep);
    color: #fff;
}

.ax-demo-btn:focus-visible {
    outline: 2px solid var(--ax-accent-deep);
    outline-offset: 2px;
}

