/* ── styles.css ── */
/* ── tokens/fonts.css ── */
/* Display face. Cal Sans (the reference system's display face) is proprietary and unavailable;
   Manrope is the documented close substitute — used at 700 with negative tracking.

   Both variable fonts ship under bracket-free filenames. Google's own names carry the axis list in
   brackets (Manrope[wght].ttf), which forces a choice between literal brackets and percent-encoded
   ones in url() — and a bundler that resolves the encoded form against the real filename finds
   nothing, so the faces silently fall back to system sans in a published page. Renaming removes
   the ambiguity: keep new axis fonts bracket-free too. */
/* @font-face Manrope 200 800 normal: declared by tokens.json (fonts/Manrope-Variable.ttf) */
/* UI + body face across all Latin surfaces. */
/* @font-face Inter 100 900 normal: declared by tokens.json (fonts/Inter-Variable.ttf) */
/* Arabic face for the /ar/ RTL surface — display and body alike. */
/* @font-face IBM Plex Sans Arabic 400 normal: declared by tokens.json (fonts/IBMPlexSansArabic-Regular.ttf) */
/* @font-face IBM Plex Sans Arabic 500 normal: declared by tokens.json (fonts/IBMPlexSansArabic-Medium.ttf) */
/* @font-face IBM Plex Sans Arabic 600 normal: declared by tokens.json (fonts/IBMPlexSansArabic-SemiBold.ttf) */
/* @font-face IBM Plex Sans Arabic 700 normal: declared by tokens.json (fonts/IBMPlexSansArabic-Bold.ttf) */
:root{
}
[dir="rtl"],[lang="ar"]{--font-display:var(--font-arabic);--font-ui:var(--font-arabic)}

/* ── styles.css ── */

/* ── tokens/colors.css ── */
:root{
}

/* ── styles.css ── */

/* ── tokens/typography.css ── */
:root{
}
.lx-display-xl{font-family:var(--font-display);font-size:var(--display-xl-size);font-weight:var(--display-xl-weight);line-height:var(--display-xl-lh);letter-spacing:var(--display-xl-track)}
.lx-display-lg{font-family:var(--font-display);font-size:var(--display-lg-size);font-weight:var(--display-lg-weight);line-height:var(--display-lg-lh);letter-spacing:var(--display-lg-track)}
.lx-display-md{font-family:var(--font-display);font-size:var(--display-md-size);font-weight:var(--display-md-weight);line-height:var(--display-md-lh);letter-spacing:var(--display-md-track)}
.lx-display-sm{font-family:var(--font-display);font-size:var(--display-sm-size);font-weight:var(--display-sm-weight);line-height:var(--display-sm-lh);letter-spacing:var(--display-sm-track)}
.lx-title-lg{font-family:var(--font-ui);font-size:var(--title-lg-size);font-weight:var(--title-lg-weight);line-height:var(--title-lg-lh);letter-spacing:var(--title-lg-track)}
.lx-title-md{font-family:var(--font-ui);font-size:var(--title-md-size);font-weight:var(--title-md-weight);line-height:var(--title-md-lh)}
.lx-title-sm{font-family:var(--font-ui);font-size:var(--title-sm-size);font-weight:var(--title-sm-weight);line-height:var(--title-sm-lh)}
.lx-body-md{font-family:var(--font-ui);font-size:var(--body-md-size);font-weight:400;line-height:var(--body-md-lh)}
.lx-body-sm{font-family:var(--font-ui);font-size:var(--body-sm-size);font-weight:400;line-height:var(--body-sm-lh)}
.lx-caption{font-family:var(--font-ui);font-size:var(--caption-size);font-weight:var(--caption-weight);line-height:var(--caption-lh)}
.lx-eyebrow{font-family:var(--font-ui);font-size:var(--eyebrow-size);font-weight:var(--eyebrow-weight);line-height:var(--eyebrow-lh);letter-spacing:var(--eyebrow-track);text-transform:uppercase}
/* Arabic display drops the Latin negative tracking — it damages Arabic joins. */
[dir="rtl"] .lx-display-xl,[dir="rtl"] .lx-display-lg,[dir="rtl"] .lx-display-md,[dir="rtl"] .lx-display-sm,[dir="rtl"] .lx-title-lg{letter-spacing:0}
[dir="rtl"] .lx-eyebrow{letter-spacing:0}

/* ── styles.css ── */

/* ── tokens/spacing.css ── */
:root{
}

/* ── styles.css ── */

/* ── tokens/radius.css ── */
:root{
}

/* ── styles.css ── */

/* ── tokens/elevation.css ── */
:root{
}

/* ── styles.css ── */

/* ── tokens/backdrop.css ── */
:root{        /* the white blocks' own width — the content measure */
  /* The rails land exactly on the content column's edges — they measure the layout, they do not
     float beside it. An earlier version offset them by a 72px gutter and the lines then read as
     unrelated to the blocks they were supposed to be tracing. */
  --rail-inset:600px;
}

/* ── styles.css ── */

/* ── tokens/base.css ── */
*,*::before,*::after{box-sizing:border-box}
body{margin:0;font-family:var(--font-ui);font-size:var(--body-md-size);line-height:var(--body-md-lh);color:var(--text-body);background:var(--surface-page);-webkit-font-smoothing:antialiased}
h1,h2,h3{font-family:var(--font-display);color:var(--text-heading);margin:0}
h4,h5,h6,p{margin:0}
a{color:var(--text-link);text-decoration:none}
a:hover{color:var(--brass-strong);text-decoration:underline;text-underline-offset:3px}
a:active{color:var(--primary-active)}
button{font-family:inherit}
img{display:block;max-width:100%}
::selection{background:var(--brass-soft);color:var(--ink)}

/* ── styles.css ── */

/* ── components/backdrop.css ── */
/* Drawing-sheet backdrop.
   Gray page ground, two continuous vertical rails, and a horizontal rule at every band boundary
   with a bold cross where a rule meets a rail.

   ONE AXIS, SHARED BY EVERYTHING. Each rail has a single axis at `50% ∓ var(--rail-inset)`, and
   every mark — the rail itself, the cross's vertical arm, the cross's horizontal arm — is drawn
   symmetrically about that axis: the 1px lines span axis ± 0.5px, the arms span axis ± the arm
   length. Getting this wrong is what made earlier versions render a tee instead of a cross:
     · a 15px arm placed with `background-position: calc(50% - inset)` lands ~7.5px off, because
       position percentages resolve against (positioning area − image width), not the box;
     · a rail drawn as [axis − 1px, axis] with an arm centred on `axis` is 0.5px out of true.
   So every layer is a FULL-WIDTH gradient with explicit stops — gradient stops resolve against
   the gradient box, so rails and arms agree by construction — and all spans are ± about the axis.

   All of it is pure background: no extra DOM, no pointer interference, never animated. */

.lx-sheet{position:relative;isolation:isolate;background-color:var(--sheet-ground)}
.lx-sheet>*{position:relative;z-index:1}

/* The two continuous vertical rails, on the content column's edges. */
.lx-sheet::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(to right,
    transparent calc(50% - var(--rail-inset) - 0.5px),
    var(--sheet-line) calc(50% - var(--rail-inset) - 0.5px) calc(50% - var(--rail-inset) + 0.5px),
    transparent calc(50% - var(--rail-inset) + 0.5px) calc(50% + var(--rail-inset) - 0.5px),
    var(--sheet-line) calc(50% + var(--rail-inset) - 0.5px) calc(50% + var(--rail-inset) + 0.5px),
    transparent calc(50% + var(--rail-inset) + 0.5px));
  background-repeat:no-repeat;background-size:100% 100%}

.lx-sheet--dark{background-color:var(--surface-dark)}
.lx-sheet--dark::before{background-image:linear-gradient(to right,
  transparent calc(50% - var(--rail-inset) - 0.5px),
  var(--sheet-line-dark) calc(50% - var(--rail-inset) - 0.5px) calc(50% - var(--rail-inset) + 0.5px),
  transparent calc(50% - var(--rail-inset) + 0.5px) calc(50% + var(--rail-inset) - 0.5px),
  var(--sheet-line-dark) calc(50% + var(--rail-inset) - 0.5px) calc(50% + var(--rail-inset) + 0.5px),
  transparent calc(50% + var(--rail-inset) + 0.5px))}

/* A band boundary. The pseudo-element is --sheet-cross-size tall and centred on the boundary, so
   the vertical arm reaches equally above and below the rule; the rule sits on its centre line. */
.lx-crossrule,.lx-crossrule--top{position:relative}
.lx-crossrule::before,.lx-crossrule::after,.lx-crossrule--top::before{content:"";position:absolute;inset-inline:0;height:var(--sheet-cross-size);z-index:0;pointer-events:none;
  background-image:
    /* vertical arms — full height of this element, on the rail axes */
    linear-gradient(to right,
      transparent calc(50% - var(--rail-inset) - 0.5px),
      var(--sheet-cross) calc(50% - var(--rail-inset) - 0.5px) calc(50% - var(--rail-inset) + 0.5px),
      transparent calc(50% - var(--rail-inset) + 0.5px) calc(50% + var(--rail-inset) - 0.5px),
      var(--sheet-cross) calc(50% + var(--rail-inset) - 0.5px) calc(50% + var(--rail-inset) + 0.5px),
      transparent calc(50% + var(--rail-inset) + 0.5px)),
    /* horizontal arms — --sheet-cross-arm either side of each axis */
    linear-gradient(to right,
      transparent calc(50% - var(--rail-inset) - var(--sheet-cross-arm)),
      var(--sheet-cross) calc(50% - var(--rail-inset) - var(--sheet-cross-arm)) calc(50% - var(--rail-inset) + var(--sheet-cross-arm)),
      transparent calc(50% - var(--rail-inset) + var(--sheet-cross-arm)) calc(50% + var(--rail-inset) - var(--sheet-cross-arm)),
      var(--sheet-cross) calc(50% + var(--rail-inset) - var(--sheet-cross-arm)) calc(50% + var(--rail-inset) + var(--sheet-cross-arm)),
      transparent calc(50% + var(--rail-inset) + var(--sheet-cross-arm))),
    /* the continuous rule */
    linear-gradient(to right,var(--sheet-line),var(--sheet-line));
  background-size:100% 100%,100% 1px,100% 1px;
  background-position:0 0,0 center,0 center;
  background-repeat:no-repeat}
.lx-crossrule::before,.lx-crossrule--top::before{inset-block-start:calc(var(--sheet-cross-size) / -2)}
.lx-crossrule::after{inset-block-end:calc(var(--sheet-cross-size) / -2)}

@media(max-width:1264px){:root{--rail-inset:calc(50vw - var(--page-pad))}}

/* ── styles.css ── */

/* ── components/interactions.css ── */
/* Interaction, RTL and responsive states for the component layer.
   Inline styles cannot express :hover / :active / :focus-visible or media queries, so every
   component emits a stable lxc-* class hook and the states live here. Consumers get these
   for free by linking styles.css — do not re-declare them per surface. */

/* --- Button --- */
.lxc-btn img{transition:transform var(--duration-fast) var(--ease-standard)}
.lxc-btn--primary:not(:disabled):hover{background:#1c1c1c}
.lxc-btn--primary:not(:disabled):active{background:var(--primary-active)}
.lxc-btn--secondary:not(:disabled):hover{border-color:#d4d4d8}
.lxc-btn--secondary:not(:disabled):active{background:var(--surface-soft)}
.lxc-btn--ghost:not(:disabled):hover{color:var(--brass-strong)}
.lxc-btn--onDark:not(:disabled):hover{background:#efefef}
.lxc-btn:focus-visible,.lxc-iconbtn:focus-visible,.lxc-link:focus-visible,.lxc-navlink:focus-visible,.lxc-pill:focus-visible{outline:2px solid var(--brass-strong);outline-offset:2px}

/* --- Icon button --- */
.lxc-iconbtn--outline:hover{border-color:#d4d4d8}
.lxc-iconbtn--solid:hover{background:#1c1c1c}

/* --- Plate card ---
   The system's one composed hover, and a reveal rather than a decoration: the description
   expands in (0fr → 1fr on the real copy height), the label rises to make room, the plate's
   ground warms to brass and its screw marks turn brass, and the tile lifts on --shadow-md.
   One 220ms curve for all of it, so the tile reads as a single object opening rather than five
   properties animating. The tile's box is fixed, so nothing below it moves.

   Both states are declared HERE, closed included. PlateCard must not set grid-template-rows or
   opacity inline: an inline closed state outranks every selector below and disables hover,
   :focus-within and the touch fallback in one stroke. */
.lxc-platecard-reveal{grid-template-rows:0fr;transition:grid-template-rows var(--duration-base) var(--ease-standard)}
.lxc-platecard-body{opacity:0;transition:opacity var(--duration-base) var(--ease-standard)}
/* The open states carry !important for the same reason the Arabic tracking reset does: any
   caller that still sets the closed state inline would otherwise outrank them and disable the
   reveal for hover, keyboard and touch at once. */
.lxc-platecard:hover{box-shadow:var(--shadow-md);border-color:var(--brass-hairline)}
.lxc-platecard:hover .lxc-platecard-reveal{grid-template-rows:1fr!important}
.lxc-platecard:hover .lxc-platecard-body{opacity:1!important}
.lxc-platecard:hover .lxc-plate{background:var(--brass-soft)}
.lxc-platecard:hover .lxc-plate-screw{background:var(--brass)}
.lxc-platecard .lxc-plate img{transition:transform var(--duration-base) var(--ease-standard)}
.lxc-platecard:hover .lxc-plate img{transform:translateY(-1px)}
.lxc-platecard:hover .lxc-plate--dark{background:var(--surface-dark-elevated)}
.lxc-platecard:hover .lxc-plate--dark .lxc-plate-screw{background:var(--brass-strong)}
/* Keyboard and touch parity: the copy must not be reachable by pointer alone. */
.lxc-platecard:focus-within .lxc-platecard-reveal{grid-template-rows:1fr!important}
.lxc-platecard:focus-within .lxc-platecard-body{opacity:1!important}
@media(hover:none){.lxc-platecard .lxc-platecard-reveal{grid-template-rows:1fr!important}.lxc-platecard .lxc-platecard-body{opacity:1!important}}
@media(prefers-reduced-motion:reduce){.lxc-platecard,.lxc-platecard *{transition:none!important}.lxc-platecard:hover .lxc-plate img{transform:none}}

/* --- Orbital diagram ---
   The ring turns; each node's content carries the inverse turn so icons and labels stay upright.
   Both share --orbit-duration, which the component sets inline. Hover anywhere pauses the whole
   diagram, so a visitor reading a label is never chasing it. */
@keyframes lxc-orbit{to{transform:rotate(360deg)}}
@keyframes lxc-orbit-counter{to{transform:rotate(-360deg)}}
.lxc-orbital-ring{animation:lxc-orbit var(--orbit-duration,54s) linear infinite}
.lxc-orbital-spin{animation:lxc-orbit-counter var(--orbit-duration,54s) linear infinite}
.lxc-orbital:hover .lxc-orbital-ring,.lxc-orbital:hover .lxc-orbital-spin,.lxc-orbital:focus-within .lxc-orbital-ring,.lxc-orbital:focus-within .lxc-orbital-spin{animation-play-state:paused}
/* The node IS a mounting plate, so its hover is the plate's hover from the capability grid —
   brass ground, brass screw marks — rather than a treatment invented for this band. */
.lxc-orbital-node:hover .lxc-plate,.lxc-orbital-node[data-active="true"] .lxc-plate{background:var(--brass-soft)}
.lxc-orbital-node:hover .lxc-plate-screw,.lxc-orbital-node[data-active="true"] .lxc-plate-screw{background:var(--brass)}
.lxc-orbital-node:focus-visible{outline:2px solid var(--brass-strong);outline-offset:4px;border-radius:var(--radius-lg)}
/* --- Icon plate ---
   Resting fills belong here rather than inline on the component: an inline background outranks
   every class selector below, which is exactly how the brass hover and the in-card brass screws
   came to be dead code. */
.lxc-plate{background:var(--canvas)}
.lxc-plate-screw{background:var(--plate-screw)}
.lxc-plate--dark{background:var(--surface-dark-elevated)}
.lxc-plate--dark .lxc-plate-screw{background:var(--plate-screw-dark)}

/* On the orbit the screws ride inboard while the ring turns, and settle out to the corners when a
   node is hovered — a single move that ENDS, not a loop. A screw oscillating under the cursor is
   fidget: it draws the eye back to itself exactly when the visitor has started reading the card.
   The offset is written as a transform rather than a custom property: --sx/--sy are per-element
   data the component supplies, but a distance declared under a component selector would read as an
   unregistered design token. */
/* Clip the diagram. The ring is a square that rotates, so its bounding rect swells toward
   side×√2 — up to ~1103px against a 780px container — and with every ancestor at overflow:visible
   that overhang became horizontal page scroll that pulsed with the animation. Nothing visible is
   lost: the outermost node sits ~348px from centre, well inside the 390px half-box, and the hover
   card already clamps itself to an 8px pad. */
.lxc-orbital{overflow:hidden}

/* EVERY PLATE IS LIVE — the system's one iconography rule.
   A plate is a switch key drawn at rest: the four screws sit parked inboard and the ground is
   neutral. Under the cursor the screws settle out hard into their corners and the ground warms to
   brass. One move that ENDS — never a loop, never a fidget. No plate anywhere is inert.

   Hovering the plate itself is the floor, so a bare plate works with no wiring at all. When the
   plate sits in a card, mark the CARD with data-plate-travel: a 92px plate inside a 320px card is
   not what a visitor aims at, and the whole card should answer. data-plate-static opts a plate
   out for the one case where it is a label rather than a target. */
.lxc-plate-screw{transform:translate(calc(var(--sx) * 4px),calc(var(--sy) * 4px))}
.lxc-plate:hover,[data-plate-travel]:hover .lxc-plate,[data-plate-travel]:focus-visible .lxc-plate,[data-plate-travel]:focus-within .lxc-plate{background:var(--brass-soft)}
.lxc-plate:hover .lxc-plate-screw,[data-plate-travel]:hover .lxc-plate-screw,[data-plate-travel]:focus-visible .lxc-plate-screw,[data-plate-travel]:focus-within .lxc-plate-screw{background:var(--brass);transform:none}
.lxc-plate--dark:hover,[data-plate-travel]:hover .lxc-plate--dark,[data-plate-travel]:focus-within .lxc-plate--dark{background:var(--surface-dark-elevated)}
.lxc-plate--dark:hover .lxc-plate-screw,[data-plate-travel]:hover .lxc-plate--dark .lxc-plate-screw,[data-plate-travel]:focus-within .lxc-plate--dark .lxc-plate-screw{background:var(--brass-strong)}
[data-plate-static] .lxc-plate-screw,[data-plate-static]:hover .lxc-plate-screw{transform:none}

.lxc-orbital-node .lxc-plate-screw{transform:translate(calc(var(--sx) * 7px),calc(var(--sy) * 7px))}
.lxc-orbital-node:hover .lxc-plate-screw,.lxc-orbital-node[data-active="true"] .lxc-plate-screw{transform:none}
/* Reduced motion keeps the colour half of the rule and drops the travel: the plate still answers
   the cursor, it just answers without moving. */
@media(prefers-reduced-motion:reduce){.lxc-plate-screw{transition:none;transform:none!important}}

/* --- Integration map ---
   One dash travelling each connector: the diagram's claim is that the house's subsystems all
   report to one place, and a moving dash is the shortest way to say "this line carries something".
   It pauses under the cursor for the same reason the orbit does — a visitor reading a card should
   not have movement in the corner of their eye. The hub's ring breathes once every three seconds
   and never scales the tile itself, so nothing reflows. */
@keyframes lxc-imap-flow{from{stroke-dashoffset:960}to{stroke-dashoffset:-40}}
@keyframes lxc-imap-ping{0%{transform:scale(1);opacity:.32}70%,100%{transform:scale(1.09);opacity:0}}
.lxc-imap-flow{animation:lxc-imap-flow 4.5s linear infinite}
.lxc-imap-ping{animation:lxc-imap-ping 3s var(--ease-standard) infinite}
.lxc-imap:hover .lxc-imap-flow,.lxc-imap:focus-within .lxc-imap-flow{animation-play-state:paused}
.lxc-imap-node:focus-visible{outline:2px solid var(--brass-strong);outline-offset:4px;border-radius:var(--radius-lg)}
/* The open card keeps its node lit: plates are live on hover already, but the card can be open
   while the pointer has moved onto the card itself. */
.lxc-imap-node[data-active="true"] .lxc-plate{background:var(--brass-soft)}
.lxc-imap-node[data-active="true"] .lxc-plate-screw{background:var(--brass);transform:none}
/* A node we manufacture is brass at rest \u2014 the one place a resting plate is not neutral, because
   the whole diagram exists to show which two of the six are ours. */
.lxc-imap-node[data-own="true"] .lxc-plate{background:var(--brass-soft)}
.lxc-imap-node[data-own="true"] .lxc-plate-screw{background:var(--brass)}
@media(prefers-reduced-motion:reduce){.lxc-imap-flow,.lxc-imap-ping{animation:none}.lxc-imap-ping{opacity:.2}}

/* Inside the card the plate is a label rather than a target: screws hard into the corners, in the
   brass the wordmark's dot uses — the same mark, doing the same job of saying "ours". */
.lxc-orbital-card .lxc-plate-screw{background:var(--brass);transform:none}

/* --- The function hue map ---
   The system's ONE licensed exception to brass-only. A plate that stands for a house FUNCTION may
   take that function's colour under the cursor: the ground fills, the glyph inverts to white, the
   screw marks go translucent. Opt in with data-fn-color plus data-fn="<icon name>" on the element
   the cursor targets (the node button, or the card containing the plate).

   It reads as a system rather than a rainbow because the hues are siblings, not a spectrum: all
   eight sit at brass's own lightness and chroma, oklch(0.62 0.11 …), and only the hue turns. So
   lighting IS the brass anchor and the other seven are its relatives. The colours themselves are
   named tokens in tokens/colors.css; what follows only maps an icon name onto one.

   Two rules. Never tint TEXT with these: at this lightness a hue clears 3:1 for a glyph but not
   4.5:1 for small type, so labels stay --ink / --brass-strong and the plate carries the colour.
   And never extend this to a plate that is not a function — everywhere else, hover is brass.

   Placed after the generic plate and node rules on purpose: these selectors tie with them on
   specificity, so source order is what makes them win. Never move this block above them. */
[data-fn-color][data-fn="lightbulb"]{}
[data-fn-color][data-fn="thermometer"]{--fn:var(--fn-climate)}
[data-fn-color][data-fn="blinds"]{--fn:var(--fn-shading)}
[data-fn-color][data-fn="chart-column"]{--fn:var(--fn-energy)}
[data-fn-color][data-fn="lock"]{--fn:var(--fn-access)}
[data-fn-color][data-fn="droplets"]{--fn:var(--fn-water)}
[data-fn-color][data-fn="speaker"]{--fn:var(--fn-audio)}
[data-fn-color][data-fn="wifi"]{--fn:var(--fn-voice)}
[data-fn-color] .lxc-plate,[data-fn-color] .lxc-plate img{transition:background var(--duration-base) var(--ease-standard),border-color var(--duration-base) var(--ease-standard),filter var(--duration-base) var(--ease-standard)}
[data-fn-color][data-fn]:hover .lxc-plate,[data-fn-color][data-fn]:focus-visible .lxc-plate,[data-fn-color][data-fn][data-active="true"] .lxc-plate{background:var(--fn);border-color:transparent}
[data-fn-color][data-fn]:hover .lxc-plate img,[data-fn-color][data-fn]:focus-visible .lxc-plate img,[data-fn-color][data-fn][data-active="true"] .lxc-plate img{filter:brightness(0) invert(1)}
[data-fn-color][data-fn]:hover .lxc-plate-screw,[data-fn-color][data-fn]:focus-visible .lxc-plate-screw,[data-fn-color][data-fn][data-active="true"] .lxc-plate-screw{background:rgba(255,255,255,0.55)}

/* The card arrives, it does not fly: 8px and a fade on the standard curve. */
@keyframes lxc-orbital-card-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.lxc-orbital-card{animation:lxc-orbital-card-in var(--duration-base) var(--ease-standard)}
.lxc-orbital-chip:hover{border-color:var(--brass-hairline);color:var(--brass-strong)}
.lxc-orbital-chip:focus-visible,.lxc-orbital-open:focus-visible{outline:2px solid var(--brass-strong);outline-offset:2px}
.lxc-orbital-open:hover{background:#1c1c1c}
@media(prefers-reduced-motion:reduce){.lxc-orbital-card{animation:none}}
@media(prefers-reduced-motion:reduce){.lxc-orbital-ring,.lxc-orbital-spin{animation:none}}

/* --- Links --- */
.lxc-link:hover{color:var(--brass-strong)}
.lxc-link--onDark:hover{color:var(--on-dark)}
/* Nav hover is a capsule that materialises around the link — border and fill, not a colour
   change alone. Each link already reserves a 1px transparent border and pill radius, so the
   capsule appears in place without shifting a single glyph. */
.lxc-navlink:hover,.lxc-navdoor:hover{color:var(--ink);background:var(--surface-soft);border-color:var(--hairline)}
.lxc-navlink[aria-current="page"],.lxc-navdoor[aria-current="page"]{background:var(--surface-soft);border-color:var(--hairline)}
.lxc-navdoor:focus-visible{outline:2px solid var(--brass-strong);outline-offset:3px}
.lxc-footer-link:hover{color:var(--on-dark)}
.lxc-footer-link:hover img{opacity:.9}
.lxc-social:hover{background:var(--surface-dark-elevated);border-color:var(--muted)}
.lxc-social:hover img{opacity:1}
.lxc-social:focus-visible{outline:2px solid var(--brass);outline-offset:2px}
.lxc-footer-send{transition:transform var(--duration-fast) var(--ease-standard),background var(--duration-fast) var(--ease-standard)}
.lxc-footer-send:hover{transform:scale(1.06);background:var(--brass-strong)}
.lxc-footer-send:focus-visible{outline:2px solid var(--brass);outline-offset:2px}

/* --- Nav island sheen ---
   On hover a light runs around the island's own contour. It is stroked on an SVG rounded rect that
   inherits the island's radius, with pathLength="100" so the dash maths is in percent and needs no
   measurement of a max-content box. Three offset strokes of rising opacity make the tail.

   A conic gradient masked to the ring is the other way to do this, but it needs an @property angle
   to rotate, and a custom property declared for a component reads to the design-system compiler as
   an unregistered token. Stroking the real path costs nothing and traces the corners exactly. */
/* The island's surface by scroll depth. At rest there is no card at all — the links sit on the
   page. One step in it becomes a white block with a hairline; one step further the edge deepens
   and the shadow lifts. After that it holds: the movement belongs to arriving, not to scrolling.
   Declared here, never inline on the component, or the inline surface would outrank every state.
   `position: relative` belongs in this rule too — the sheen SVG is absolutely positioned against
   it, and depending on an inline leftover for that is how it silently breaks. */
.lxc-navisland{position:relative;background:transparent;border:1px solid transparent;box-shadow:none;
  transition:background var(--duration-base) var(--ease-standard),border-color var(--duration-base) var(--ease-standard),box-shadow var(--duration-base) var(--ease-standard)}
.lxc-navisland[data-lift="1"]{background:var(--canvas);border-color:var(--hairline-soft);box-shadow:var(--shadow-sm)}
.lxc-navisland[data-lift="2"]{background:var(--canvas);border-color:var(--hairline);box-shadow:var(--shadow-md)}
/* The contour sheen is an island effect, so it only exists once the island does. */
.lxc-navisland[data-lift="0"] .lxc-navisland-sheen{display:none}

@keyframes lxc-sheen{to{stroke-dashoffset:-100}}
.lxc-navisland-sheen{opacity:0;transition:opacity var(--duration-base) var(--ease-standard)}
.lxc-navisland:hover .lxc-navisland-sheen,.lxc-navisland:focus-within .lxc-navisland-sheen{opacity:1}
.lxc-navisland-sheen rect{animation:lxc-sheen 3.6s linear infinite}
@media(prefers-reduced-motion:reduce){.lxc-navisland-sheen rect{animation:none}}

/* --- Project strategy --- */
.lxc-projstrategy{transition:box-shadow var(--duration-base) var(--ease-standard),border-color var(--duration-base) var(--ease-standard)}
.lxc-projstrategy:hover{box-shadow:var(--shadow-md)}

/* --- Status dots ---
   The three-state judgement used by the compatibility matrix and the room matrix. It lives here,
   in the design system's CSS closure, because a component that renders these classes is otherwise
   invisible to any consumer who only links styles.css and the bundle — which is exactly what the
   design system tells consumers to do. The <i> carries the whole mark, so without these rules the
   cell is empty rather than merely unstyled. */
.lxc-dot{display:inline-flex;align-items:center;gap:7px;font-family:var(--font-ui);font-size:13px;color:var(--text-muted)}
.lxc-dot i{width:7px;height:7px;border-radius:var(--radius-full);display:block;flex:none}
.lxc-dot--full i{background:var(--success)}
.lxc-dot--partial i{background:var(--warning)}
.lxc-dot--none i{background:var(--surface-strong)}

/* --- Room matrix --- */
.lxc-roomrow{transition:background var(--duration-fast) var(--ease-standard)}
.lxc-roomrow:not([data-active="true"]):hover{background:var(--surface-soft)}
@media(max-width:1000px){.lxc-roomdetail{grid-template-columns:1fr!important}}

/* --- Scene explorer ---
   The room's glows carry their own opacity transitions inline (level is data, so it belongs with the
   element). Only the pills and the collapse live here. The old .lxc-scene-bar rules are gone with
   the bars they styled — dead selectors in a design system are read as API by consumers. */
.lxc-scene-pill:not([aria-pressed="true"]):hover{color:var(--on-dark);border-color:var(--on-dark-soft)}
.lxc-scene-pill:focus-visible{outline:2px solid var(--brass);outline-offset:2px}
@media(prefers-reduced-motion:reduce){.lxc-scene [style*="opacity"]{transition:none!important}}
@media(max-width:1000px){.lxc-scene{grid-template-columns:1fr!important}}
/* The isometric world is a fixed 300px square so its translateZ values stay exact — percentages are
   illegal there. The room box caps at 480px so the drawing fills it instead of floating in black;
   scale the world rather than reworking geometry when the panel is narrower still. */
@media(max-width:640px){.lxc-iso{transform:translate(-50%,-50%) scale(.66) rotateX(58deg) rotateZ(40deg)!important}}

/* --- Nav pill group --- */
.lxc-pill:not([aria-pressed="true"]):hover{color:var(--ink)}

/* --- Directional glyphs flip on the Arabic surface; symmetric ones must not ---
   Keyed to data-icon, not to the src: publishing rewrites every icon src to a blob URL, so a
   [src$="arrow-right.svg"] selector silently stops matching in the published artifact. */
[dir="rtl"] [data-icon="arrow-right"],[dir="rtl"] [data-icon="chevron-right"],[dir="rtl"] [data-icon="chevron-left"]{transform:scaleX(-1)}

/* --- Arabic drops the display face's negative tracking (see readme, Bilingual rules) ---
   !important is required: the components set letter-spacing and line-height inline so they
   paint immediately, and an inline declaration outranks any selector here. */
[dir="rtl"] .lxc-hero-title,[dir="rtl"] .lxc-section-title,[dir="rtl"] .lxc-cta-title,[dir="rtl"] .lxc-price,[dir="rtl"] .lxc-tier-name{letter-spacing:0!important}
[dir="rtl"] .lxc-hero-title{line-height:1.25!important}

/* --- Responsive collapse ---
   Below 1000px the inline nav row is replaced by TopNav's own menu button, never simply
   hidden: the top bar is the only route between pages, so removing it strands the site. */
.lxc-navtoggle{display:none}
/* The nav row collapses earlier than the rest of the layout. With two doors plus five
   content links plus the right-hand cluster, the inline row needs ~1240px to sit on one
   line; below that it is the menu button's job, while the page layout itself only
   reflows at 1000px. Two different breakpoints, two different reasons. */
@media(max-width:1240px){
  .lxc-navlinks{display:none!important}
  .lxc-navtoggle{display:inline-flex!important}
}
@media(max-width:1000px){
  .lxc-hero-grid{grid-template-columns:1fr!important;gap:var(--space-xl)!important}
  .lxc-hero-title{font-size:44px!important;letter-spacing:-1.4px!important}
  .lxc-footer-grid{grid-template-columns:1fr 1fr!important}
}
.lxc-navtoggle:hover{border-color:#d4d4d8}

/* ── styles.css ── */


/* ── tokens/fonts.css ── */

/* ── tokens/colors.css ── */

/* ── tokens/typography.css ── */

/* ── tokens/spacing.css ── */

/* ── tokens/radius.css ── */

/* ── tokens/elevation.css ── */

/* ── tokens/backdrop.css ── */

/* ── tokens/base.css ── */

/* ── components/backdrop.css ── */

/* ── components/interactions.css ── */

