/* Palette — every color the site paints with.
   Loaded by every page ahead of its own stylesheet, so a theme is one
   <html data-theme> away. The default set is "dune"; the blocks after it are
   the alternates. A theme is a complete description of the page rather than a
   tint laid over a light one, which is what lets the dark ones work.

   Every theme here is light or mid-light. The split between --hair-rgb and
   --shade-rgb, and tokens like --on-brand, exist so a dark theme could be added
   as one more block without touching a single rule elsewhere — keep them honest
   if you add one.

   The ones that are easy to get wrong:

     --hair-rgb    foreground-derived hairlines and faint tints.
     --shade-rgb   shadows. Always the dark end, whatever the theme.
     --on-brand    text and icons sitting ON a solid brand fill.
     --chip-ink    text on the small white pills that float over photography.
                   Those pills stay white in every theme, so this stays dark —
                   it must not follow --brand.
     --panel-*     the checkout block, the one deliberately inverted surface.
     --surface-input / --surface-sunk
                   controls resting on a card, and the tinted inner panel a card
                   holds. Both are a step in from --bg-card.
     --chip-bg / --on-scrim
                   the companions to --chip-ink. --chip-bg is the white pill
                   itself; --on-scrim is type sitting on rgba(var(--scrim-rgb)).
                   Both stay white here for the same reason --chip-ink stays
                   dark: the photograph underneath is what varies, not the theme.
     --dim          the measurement blue, constant across themes on purpose.
                    See its note below.
     --gilt         the decorative gold filament, likewise constant. Distinct
                    from --panel-ico, which only reads on the dark panel.

   Nothing outside this file should hardcode a color. The three cases that used
   to justify it - white type on a photo scrim, the white pill over a photo, and
   a solid error fill - now have tokens (--on-scrim, --chip-bg, --danger). What
   is left is a third-party brand glyph (the Facebook and Google marks, the card
   badges) and a real material color a customer is choosing: a paint hex, a wood
   tone, a metal finish. Those describe an object, not the interface, and must
   not follow the palette. */

/* THE DEFAULT — "Dune" — LIGHT - cream white and a soft clay. The warm option
   done bright, so it sits next to maple without going back to beige. The
   default since 2026-09-07. */
:root{
    --scheme:light;
    --bg:#ffffff;
    --bg-card:#ffffff;
    --surface-input:#ffffff;
    --surface-sunk:#fbf8f4;
    --band-rgb:250,247,243;
    --line:#efeae3;
    --wash-1:rgba(190,150,110,.055);
    --wash-2:rgba(200,175,150,.04);
    --ink:#1a1815;
    /* --ink-soft is dark enough in Dune, Mist, Clay and Stone to clear 4.5:1
       on the --line-soft tint too - the builders put secondary text on that
       tint in a dozen places (segmented controls, step numbers, tags, the
       builder's row bodies). Gated in check-contrast.mjs. */
    --ink-soft:#726a61;
    --hair-rgb:35,28,20; --ink-rgb:35,28,20;
    --shade-rgb:35,28,20;
    --scrim-rgb:26,20,14;
    --brand:#9a6a4a;
    --brand-deep:#7e5439;
    --brand-soft:#f7efe7;
    --brand-rgb:154,106,74;
    --brand-grad-a:#a9785a;
    --brand-grad-b:#8a5c40;
    --on-brand:#ffffff;
    --chip-ink:#5e3e29;
    --btn-bg:#9a6a4a;
    --btn-bg-hover:#7e5439;
    --btn-ink:#ffffff;
    --btn-off:#cdc5bb;
    --pop:#9a6a4a;
    --accent:#27705a;
    --accent-soft:#e8f4ef;
    --accent-rgb:39,112,90;
    --panel-ico:#f0d9a4;
    --header-bg:rgba(255,255,255,.82);
    --sheet-bg:rgba(255,255,255,.96);
    --stage-a:#faf7f3;
    --stage-b:#ece4da;
    --panel-a:#7e5439;
    --panel-b:#5e3e29;
    --panel-ink:#f0e3d7;
    --panel-h:#ffffff;
    --panel-chip:rgba(255,255,255,.13);
    --toast-bg:#1a1815;
    --toast-fg:#faf5ef;
    --toast-link:#e0b98f;
    --foot-1:#faf7f3;
    --foot-2:#f4efe8;
    --foot-3:#eee7de;
    --foot-ink:99,90,80;
    --foot-strong:#1a1815;
    --foot-chip:rgba(154,106,74,.07);
    --foot-line:rgba(35,28,20,.09);
    --foot-rule:rgba(154,106,74,.24);
    --foot-glow:rgba(154,106,74,.06);
    --foot-ring:rgba(35,28,20,.09);
    --foot-ring-shadow:rgba(35,28,20,.09);
    --foot-ico:#9a6a4a;

    /* Semantic tints shared by every light and mid theme; the dark ones
       override these. Success reuses --accent / --accent-soft.
       Each family is soft fill / ink / hairline, plus a solid for danger,
       which is the only one that ever fills a whole surface (the error toast
       and the destructive button). */
    --danger-soft:#fdeeec; --danger-ink:#8e2d20; --danger-line:#eec4bd;
    --danger:#b3261e; --danger-deep:#8e2d20; --danger-rgb:179,38,30;
    --warn-soft:#fbf1dd; --warn-ink:#7a5412; --warn-line:#eddcb4;
    --accent-deep:#1d5a48; --accent-grad-a:#2f8a68; --accent-grad-b:#1f7a5c;
    --on-accent:#ffffff;

    /* The product-photography sweep. The seamless white the closet visualiser
       stands its cabinet on, wall and floor both — see SWEEP_WHITE's note in
       assets/closet-product.js for why that scene is white rather than a
       themed cyclorama.

       CONSTANT ACROSS THEMES, and here for the same reason --chip-bg is: what
       varies under it is the photograph, not the palette. It lives in this
       file rather than as a literal because it is read TWICE — by the CSS
       behind the canvas and by the canvas itself — and two copies of one
       backdrop is how a page flashes one white and settles on another. */
    --sweep:#ffffff;

    /* The measurement blue. Deliberately NOT --brand: a dimension line and a
       selection outline have to read as instrumentation sitting on top of the
       room, not as part of it, so this one color stays constant across themes.
       Shared by the 3D planners, in CSS and in Three.js. */
    --dim:#2653e8; --dim-rgb:38,83,232;

    /* The gold filament. Universal for the same reason as --dim: it reads as
       metal laid ON a surface, not as one of the surface's own tones. It is NOT
       --panel-ico, which is the pale gold that has to survive the dark inverted
       panel - on a light card that one lands at 1.38-1.97:1 (i.e. invisible),
       while this holds 2.44-2.59:1 across all five. Decorative only; never put
       type on it. */
    --gilt:#c79a3a;

    /* Surfaces that float over photography. These stay white in every theme for
       the same reason --chip-ink stays dark - the photo underneath is the
       variable, not the palette. A dark theme overrides the pair together. */
    --chip-bg:rgba(255,255,255,.92);
    --on-scrim:#ffffff;

    /* Type and measure. Here so a page never restates a font stack or a page
       width; both were drifting between copies before. */
    --font-sans:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
    --font-serif:'Fraunces',Georgia,'Times New Roman',serif;
    --wrap-max:1200px;

    /* Derived - these resolve per theme through the triplets above, so they
       never need restating in a theme block. */
    --line-soft:rgba(var(--hair-rgb),.07);
    --line-strong:rgba(var(--hair-rgb),.17);
    --ok-line:rgba(var(--accent-rgb),.38);
    --danger-fill:linear-gradient(180deg,var(--danger),var(--danger-deep));
    --accent-fill:linear-gradient(180deg,var(--accent-grad-a),var(--accent-grad-b));
    --chip-line:rgba(var(--hair-rgb),.08);
    --glass-bg:var(--chip-bg);
    --glass-line:rgba(var(--hair-rgb),.08);
    --surface-hover:rgba(var(--brand-rgb),.055);
    --stage-line:rgba(var(--hair-rgb),.10);
    --dim-soft:rgba(var(--dim-rgb),.14);
    --btn-off-ink:rgba(var(--hair-rgb),.78);
    --focus-ring:var(--brand);
    /* The inverted panel is dark in every theme, so its two extra values are
       white-with-alpha rather than per-theme hexes. */
    --panel-line:rgba(255,255,255,.14);
    --panel-ink-soft:rgba(255,255,255,.72);

    /* Shared by every theme. */
    --section-y:clamp(64px,7.2vw,104px);
    --shadow:0 1px 2px rgba(var(--shade-rgb),.03),0 14px 34px -18px rgba(var(--shade-rgb),.30);
    --shadow-lg:0 2px 6px rgba(var(--shade-rgb),.04),0 34px 70px -28px rgba(var(--shade-rgb),.34);
    --shadow-card:0 1px 2px rgba(var(--shade-rgb),.04),0 18px 40px -14px rgba(var(--shade-rgb),.28);
    --radius-sm:12px;
    --radius:20px;
    --radius-lg:26px;
    --radius-pill:999px;
    /* THE CONTENT RADIUS. Near-square, and the direction the site is moving in:
       a 26px card reads as an app surface, a 2px one reads as a drawn panel,
       which is what a shop selling measured casework should look like. One
       token here, so no two pages disagree about what a card is.

       Squaring anything still on --radius / --radius-lg means swapping its
       card and control radii to this and checking nothing that should stay
       round (the header, the chips over photography, a swatch) went square
       with them. */
    --r-hard:2px;
}

/* "Mist" - LIGHT - cool white with a soft blue. The quietest of the light themes;
   the photography supplies all the warmth. */
html[data-theme="mist"]{
    --scheme:light;
    --bg:#ffffff;
    --bg-card:#ffffff;
    --surface-input:#ffffff;
    --surface-sunk:#f7f9fc;
    --band-rgb:244,247,251;
    --line:#e9edf3;
    --wash-1:rgba(99,132,193,.055);
    --wash-2:rgba(120,170,190,.045);
    --ink:#151922;
    --ink-soft:#636c78;
    --hair-rgb:21,25,34; --ink-rgb:21,25,34;
    --shade-rgb:21,25,34;
    --scrim-rgb:15,19,26;
    --brand:#4a6fa5;
    --brand-deep:#3b5b8a;
    --brand-soft:#eef3fa;
    --brand-rgb:74,111,165;
    --brand-grad-a:#5a7fb5;
    --brand-grad-b:#3f6294;
    --on-brand:#ffffff;
    --chip-ink:#2c4568;
    --btn-bg:#4a6fa5;
    --btn-bg-hover:#3b5b8a;
    --btn-ink:#ffffff;
    --btn-off:#c0c6cf;
    --pop:#4a6fa5;
    --accent:#27705a;
    --accent-soft:#e8f4ef;
    --accent-rgb:39,112,90;
    --panel-ico:#edd39a;
    --header-bg:rgba(255,255,255,.82);
    --sheet-bg:rgba(255,255,255,.96);
    --stage-a:#f4f7fb;
    --stage-b:#e6ecf4;
    --panel-a:#3b5b8a;
    --panel-b:#2c4568;
    --panel-ink:#dfe8f4;
    --panel-h:#ffffff;
    --panel-chip:rgba(255,255,255,.13);
    --toast-bg:#151922;
    --toast-fg:#f2f5fa;
    --toast-link:#a8c4e6;
    --foot-1:#f6f8fc;
    --foot-2:#eff3f9;
    --foot-3:#e7eef7;
    --foot-ink:88,98,112;
    --foot-strong:#151922;
    --foot-chip:rgba(74,111,165,.07);
    --foot-line:rgba(21,25,34,.09);
    --foot-rule:rgba(74,111,165,.24);
    --foot-glow:rgba(74,111,165,.06);
    --foot-ring:rgba(21,25,34,.09);
    --foot-ring-shadow:rgba(21,25,34,.09);
    --foot-ico:#4a6fa5;
}


/* "Paper" — LIGHT - monochrome. Near-black buttons and type, with one warm copper
     spark held back for the headline and the eyebrows. */
html[data-theme="paper"]{
    --scheme:light;
    --bg:#ffffff;
    --bg-card:#ffffff;
    --surface-input:#ffffff;
    --surface-sunk:#f8f8f6;
    --band-rgb:246,246,244;
    --line:#e9e8e4;
    --wash-1:rgba(176,96,58,.04);
    --wash-2:rgba(140,136,128,.03);
    --ink:#131211;
    --ink-soft:#6c6a64;
    --hair-rgb:19,18,17; --ink-rgb:19,18,17;
    --shade-rgb:19,18,17;
    --scrim-rgb:14,13,12;
    --brand:#2f2c27;
    --brand-deep:#1c1a17;
    --brand-soft:#f1f0ec;
    --brand-rgb:47,44,39;
    --brand-grad-a:#3b3730;
    --brand-grad-b:#22201c;
    --on-brand:#ffffff;
    --chip-ink:#1c1a17;
    --btn-bg:#22201c;
    --btn-bg-hover:#131211;
    --btn-ink:#ffffff;
    --btn-off:#c9c7c1;
    --pop:#b0603a;
    --accent:#27705a;
    --accent-soft:#e8f4ef;
    --accent-rgb:39,112,90;
    --panel-ico:#d9b45c;
    --header-bg:rgba(255,255,255,.82);
    --sheet-bg:rgba(255,255,255,.96);
    --stage-a:#f6f6f4;
    --stage-b:#e8e7e3;
    --panel-a:#22201c;
    --panel-b:#131211;
    --panel-ink:#e6e4df;
    --panel-h:#ffffff;
    --panel-chip:rgba(255,255,255,.12);
    --toast-bg:#131211;
    --toast-fg:#f5f4f1;
    --toast-link:#d8b48f;
    --foot-1:#f7f7f5;
    --foot-2:#f2f1ee;
    --foot-3:#ebeae6;
    --foot-ink:90,88,82;
    --foot-strong:#131211;
    --foot-chip:rgba(47,44,39,.06);
    --foot-line:rgba(19,18,17,.09);
    --foot-rule:rgba(19,18,17,.16);
    --foot-glow:rgba(176,96,58,.05);
    --foot-ring:rgba(19,18,17,.09);
    --foot-ring-shadow:rgba(19,18,17,.09);
    --foot-ico:#b0603a;
}

/* “Clay” — MID - greige with cream cards. The cosiest of the set and the
   closest in spirit to the original scheme, minus the mud. */
html[data-theme="clay"]{
    --scheme:light;
    --bg:#ece7e0;
    --bg-card:#faf8f5;
    --surface-input:#ffffff;
    --surface-sunk:#f4f0ea;
    --band-rgb:229,222,213;
    --line:#ddd5ca;
    --wash-1:rgba(160,130,100,.06);
    --wash-2:rgba(180,160,140,.045);
    --ink:#1e1a15;
    --ink-soft:#665d52;
    --hair-rgb:35,29,22; --ink-rgb:35,29,22;
    --shade-rgb:35,29,22;
    --scrim-rgb:26,21,15;
    --brand:#8a5a3c;
    --brand-deep:#6d452d;
    --brand-soft:#f0e6da;
    --brand-rgb:138,90,60;
    --brand-grad-a:#996749;
    --brand-grad-b:#7a4e34;
    --on-brand:#ffffff;
    --chip-ink:#6d452d;
    --btn-bg:#8a5a3c;
    --btn-bg-hover:#6d452d;
    --btn-ink:#ffffff;
    --btn-off:#c4b9ab;
    --pop:#8a5a3c;
    --accent:#27705a;
    --accent-soft:#dfeee7;
    --accent-rgb:39,112,90;
    --panel-ico:#e8cf96;
    --header-bg:rgba(236,231,224,.84);
    --sheet-bg:rgba(236,231,224,.97);
    --stage-a:#e9e3da;
    --stage-b:#d8cec1;
    --panel-a:#6d452d;
    --panel-b:#4f3120;
    --panel-ink:#f0e4d8;
    --panel-h:#ffffff;
    --panel-chip:rgba(255,255,255,.13);
    --toast-bg:#1e1a15;
    --toast-fg:#f7f2ec;
    --toast-link:#dbb289;
    --foot-1:#e6e0d8;
    --foot-2:#e0d9d0;
    --foot-3:#d9d1c6;
    --foot-ink:86,77,67;
    --foot-strong:#1e1a15;
    --foot-chip:rgba(138,90,60,.08);
    --foot-line:rgba(35,29,22,.11);
    --foot-rule:rgba(138,90,60,.26);
    --foot-glow:rgba(138,90,60,.06);
    --foot-ring:rgba(35,29,22,.11);
    --foot-ring-shadow:rgba(35,29,22,.11);
    --foot-ico:#8a5a3c;
}

/* "Stone" - MID - warm neutral grey. */
html[data-theme="stone"]{
    --scheme:light;
    --bg:#e9e8e5;
    --bg-card:#f9f9f8;
    --surface-input:#ffffff;
    --surface-sunk:#f2f1ee;
    --band-rgb:225,224,220;
    --line:#dbd9d4;
    --wash-1:rgba(147,84,47,.045);
    --wash-2:rgba(140,136,128,.035);
    --ink:#171614;
    --ink-soft:#605e59;
    --hair-rgb:24,23,20; --ink-rgb:24,23,20;
    --shade-rgb:24,23,20;
    --scrim-rgb:18,17,15;
    --brand:#55514a;
    --brand-deep:#423f39;
    --brand-soft:#eceae6;
    --brand-rgb:85,81,74;
    --brand-grad-a:#625d55;
    --brand-grad-b:#484440;
    --on-brand:#ffffff;
    --chip-ink:#423f39;
    --btn-bg:#55514a;
    --btn-bg-hover:#423f39;
    --btn-ink:#ffffff;
    --btn-off:#bab7b1;
    --pop:#93542f;
    --accent:#27705a;
    --accent-soft:#e2efe9;
    --accent-rgb:39,112,90;
    --panel-ico:#dcc08a;
    --header-bg:rgba(233,232,229,.84);
    --sheet-bg:rgba(233,232,229,.97);
    --stage-a:#e6e5e1;
    --stage-b:#d8d6d1;
    --panel-a:#423f39;
    --panel-b:#2c2a26;
    --panel-ink:#e8e5df;
    --panel-h:#ffffff;
    --panel-chip:rgba(255,255,255,.12);
    --toast-bg:#171614;
    --toast-fg:#f5f4f1;
    --toast-link:#d8b48f;
    --foot-1:#e4e3df;
    --foot-2:#dedcd8;
    --foot-3:#d7d5d0;
    --foot-ink:88,86,80;
    --foot-strong:#171614;
    --foot-chip:rgba(85,81,74,.07);
    --foot-line:rgba(24,23,20,.10);
    --foot-rule:rgba(24,23,20,.18);
    --foot-glow:rgba(147,84,47,.05);
    --foot-ring:rgba(24,23,20,.10);
    --foot-ring-shadow:rgba(24,23,20,.10);
    --foot-ico:#93542f;
}

/* ═══ PAPER ══════════════════════════════════════════════════════════════
   The build sheet at /admin gets printed and carried to a bench, and the
   admin honours whatever palette is set — so on a dark theme the sheet would
   come out of the printer as a black page, or (with backgrounds stripped by
   the browser) as pale grey text on white.

   Rather than have the print stylesheet restate every colour, the PALETTE
   itself goes to paper here and every existing var() downstream follows. One
   block, and admin.css needs no colour rules at all.

   `html` and not `:root`, deliberately: they are the same element, but
   scripts/check-theme.mjs reads every `:root {…}` block in this file as an
   alternate palette and would demand this one restate all 100-odd tokens.
   It restates the dozen that end up on paper, which is the point.

   …but a SELECTOR LIST and doubled attributes, which needs explaining. A bare
   `html{…}` is specificity (0,0,1): one type selector and nothing else. It
   loses to all three of the things that also write these tokens —

     :root                          (0,1,0)  a pseudo-class outranks a type,
                                             so the DEFAULT palette beats it
     html[data-theme="clay"]        (0,1,1)  and so does every named theme
     html[data-admin-theme="dark"]  (0,1,1)  and so does the admin's dark block

   — and specificity is settled before source order is ever consulted, so being
   last in the file buys nothing. That is a build sheet printed in the screen
   palette: hairlines too pale to see under a table of cut dimensions, and on
   the admin's dark palette near-white ink on white paper.

   So every arm is levelled up to (0,2,1), above all three, by DOUBLING an
   attribute: `[data-theme][data-theme]` matches exactly the same elements as
   `[data-theme]` and buys nothing but rank. Rank rather than a tie is the
   point — /assets/admin-theme.css is a LATER stylesheet, so a tie at (0,1,1)
   would go to it on source order and paper would lose again. At (0,2,1) this
   no longer depends on which sheets a page links, or in what order.
   The `:not():not()` arm is the default palette: the root element with neither
   attribute, at the same (0,2,1) so all three arms rank alike. It is written
   with `html` and `:not()` rather than the obvious `:root:root` for the same
   reason as the paragraph above: `:root` immediately before a `{` reads to
   check-theme.mjs as an alternate palette.

   !important would also have worked and is the wrong tool: twenty of them here
   would outrank every legitimate print-only rule downstream, and not one of
   them would say why. Verified in a browser across all four attribute states
   before and after. Do not "simplify" this back to `html`.
   ═══════════════════════════════════════════════════════════════════════ */
@media print {
  html[data-theme][data-theme],
  html[data-admin-theme][data-admin-theme],
  html:not([data-theme]):not([data-admin-theme]){
    color-scheme: light;
    --bg:#ffffff; --bg-card:#ffffff;
    --surface-input:#ffffff; --surface-sunk:#f4f4f4; --surface-hover:#ffffff;
    /* Near-black rather than pure black: pure black on a laser printer fills
       counters on small type. */
    --ink:#111111; --ink-soft:#3f3f3f;
    --line:#8a8a8a; --line-soft:#c4c4c4;
    /* Headings keep a hint of the brand on a colour printer and fall back to
       dark grey on a mono one, which is what a build sheet gets printed on. */
    --brand:#4a4a4a; --brand-deep:#1f1f1f; --brand-soft:#f2f2f2;
    --accent:#2f2f2f; --accent-soft:#f2f2f2; --accent-deep:#1f1f1f;
    --danger:#000000; --danger-ink:#000000; --danger-soft:#ffffff; --danger-line:#8a8a8a;
    --btn-bg:#ffffff; --btn-ink:#111111; --btn-off:#ffffff;
  }
}
