/* =============================================================================
   theme.css — the hub's two editions, and the switch between them.
   -----------------------------------------------------------------------------
   Every colour in pro.css, pro.php, procode.php and lab-auth-engine.php now
   reads a token from this file. That includes the ~400 inline style="…"
   attributes in the hub, which is the whole reason it is done this way: an
   inline style beats any stylesheet rule short of !important, but a var() in an
   inline style resolves against the cascade like any other. Redefining a token
   on <html> re-themes the inline styles too, and there is not one !important in
   this file.

   Two editions:

     console   the original — near-black, one orange, glow as the depth cue
     paper     the labs.llc paper register — white stock, ink #1E262B, a 12%
               hairline, one restrained accent, and shadow instead of glow

   This file must be linked BEFORE the page's own styles on every page, since
   it is where the tokens those styles reference are declared.
   ========================================================================== */

/* ------------------------------------------------------------------ console */
:root {
    /* surfaces */
    --bg-deep:          #050505;
    --bg:               #0a0a0a;
    --bg-panel:         #0a0a0f;
    --surface-1:        #111113;
    --surface-2:        #1a1a1e;
    --surface-3:        #222222;
    --surface-slate:    #0f172a;
    --surface-slate-2:  #1f2937;

    /* lines */
    --line:             #444444;
    --line-strong:      #333333;
    --line-slate:       #334155;

    /* type */
    --text-hi:          #ffffff;
    --text:             #e0e0e0;
    --text-dim:         #aaaaaa;
    --text-mute:        #888888;
    --text-faint:       #666666;
    /* Sits on top of an accent fill, so it flips when the accent does. */
    --on-accent:        #000000;
    --text-card:        #222222;
    /* The tile's own filename. Distinct from --on-accent because the tile is
       only accent-filled in the console; on paper it is stock. */
    --text-tile:        #000000;
    /* Always white: the type badges are saturated chips in both editions. */
    --on-badge:         #ffffff;
    --code-header-bg:   #1a2338;

    /* accent */
    --accent:           #ff8800;
    --accent-hi:        #ffaa00;
    --accent-bright:    #ff9500;
    --accent-deep:      #ff6b00;
    --accent-orange:    #f97316;

    /* semantic */
    --ok:               #10b981;
    --ok-hi:            #4ade80;
    --danger:           #ef4444;
    --danger-hi:        #f87171;
    --info:             #3b82f6;
    --info-hi:          #60a5fa;
    --special:          #8b5cf6;
    --special-hi:       #c084fc;
    --warn:             #fbbf24;
    --cyan:             #67e8f9;

    /* Channel lists, not colours: every rgba() in the codebase keeps its own
       alpha and only borrows the channels. That is what lets a 61-instance
       orange glow become an ink shadow without touching 61 declarations. */
    --accent-rgb:       255, 136, 0;
    --accent-hi-rgb:    255, 170, 0;
    --accent-deep-rgb:  255, 107, 0;
    --shadow-rgb:       0, 0, 0;
    --fg-rgb:           255, 255, 255;
    --surface-1-rgb:    17, 17, 17;
    --surface-2-rgb:    20, 20, 25;
    --text-mute-rgb:    136, 136, 136;

    /* type system */

    /* Tinted plates. Each is a hue-carrying surface, so the colour coding of the
       code frames and status panels survives the edition change instead of
       flattening to one grey. */
    --tint-blue:        #0c1222;
    --tint-purple:      #160a1a;
    --tint-red:         #2a1414;
    --tint-green:       #0a1a14;
    --tint-amber:       #1a1608;
    --tint-orange:      #1a1208;
    --ok-deep:          #166534;
    --danger-fill:      #e11d48;
    --pink:             #ec4899;
    --alarm:            #ff2a00;
    --magenta:          #c026d3;
    /* Near-black type that sits on the green ALL segment. */
    --on-badge-dark:    #04120c;

    /* type system */
    --font-ui:          'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    --font-display:     'Orbitron', sans-serif;
    --font-mono:        'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    --display-weight:   700;
    --display-track:    5px;
    --display-case:     uppercase;

    color-scheme: dark;
}

/* -------------------------------------------------------------------- paper */
:root[data-theme="paper"] {
    --bg-deep:          #ffffff;
    --bg:               #ffffff;
    --bg-panel:         #fafaf8;
    --surface-1:        #fafaf8;
    --surface-2:        #f4f4f2;
    --surface-3:        #ededea;
    --surface-slate:    #f5f6f7;
    --surface-slate-2:  #eff1f3;

    --line:             rgba(30, 38, 43, 0.12);
    --line-strong:      rgba(30, 38, 43, 0.22);
    --line-slate:       rgba(30, 38, 43, 0.14);

    --text-hi:          #1e262b;
    --text:             #1e262b;
    --text-dim:         rgba(30, 38, 43, 0.64);
    --text-mute:        #717171;
    /* .45 measured 3.3:1 on the stock and this token carries the file sizes and
       hints — under the 4.5:1 floor for the smallest type on the page. .58 is
       4.7:1 and is still plainly the quietest of the four inks. */
    --text-faint:       rgba(30, 38, 43, 0.58);
    --on-accent:        #ffffff;
    --text-tile:        #1e262b;
    --on-badge:         #ffffff;
    --code-header-bg:   #ededea;
    /* Text sitting on a project card. In the console the cards are filled with
       the accent and this is near-black on orange; on paper the cards are stock
       and it has to be ink. */
    --text-card:        rgba(30, 38, 43, 0.66);

    /* #ff8800 measures 2.2:1 on white and this hub sets most of its text at
       0.6–0.85rem, so the accent steps back to a rust that reads. The brand
       orange survives where it is a fill and not a letterform — the logo badge. */
    --accent:           #c2410c;
    --accent-hi:        #9a3412;
    --accent-bright:    #b4400f;
    --accent-deep:      #7c2d12;
    --accent-orange:    #c2410c;

    /* The semantic set, darkened until each one clears 4.5:1 on the stock.
       Emerald at #10b981 measures 2.4:1 and was unreadable as small text. */
    --ok:               #047857;
    --ok-hi:            #059669;
    --danger:           #b91c1c;
    --danger-hi:        #dc2626;
    --info:             #1d4ed8;
    --info-hi:          #2563eb;
    --special:          #6d28d9;
    --special-hi:       #7c3aed;
    --warn:             #a16207;
    --cyan:             #0e7490;

    /* The glow becomes a shadow. Same declarations, same alphas — the channels
       under them are ink now, so `0 0 50px rgba(var(--accent-rgb), .25)` reads
       as paper lift instead of as a halo. */
    --accent-rgb:       30, 38, 43;
    --accent-hi-rgb:    30, 38, 43;
    --accent-deep-rgb:  30, 38, 43;
    --shadow-rgb:       30, 38, 43;
    --fg-rgb:           30, 38, 43;
    --surface-1-rgb:    250, 250, 248;
    --surface-2-rgb:    244, 244, 242;
    --text-mute-rgb:    113, 113, 113;

    /* DM Sans for everything read in sentences; the mono stays on the things
       that are actually tabular — paths, sizes, code previews. The display
       inversion is the load-bearing rule of this register: big text light and
       tightly tracked, small text heavy and positive-tracked. */

    /* The same hues as stock rather than as plate. */
    --tint-blue:        #f1f5fb;
    --tint-purple:      #f8f5fd;
    --tint-red:         #fdf3f3;
    --tint-green:       #f2faf6;
    --tint-amber:       #fdf9ef;
    --tint-orange:      #fdf6f0;
    --ok-deep:          #047857;
    --danger-fill:      #be123c;
    --pink:             #be185d;
    --alarm:            #c2410c;
    --magenta:          #a21caf;
    /* The ALL segment is white stock on paper, so its label has to be the ink
       version of the same green rather than near-black. */
    --on-badge-dark:    #ffffff;

    --font-ui:          'DM Sans', system-ui, -apple-system, sans-serif;
    --font-display:     'DM Sans', system-ui, -apple-system, sans-serif;
    --font-mono:        'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    --display-weight:   300;
    --display-track:    -0.5px;
    --display-case:     none;

    color-scheme: light;
}

/* =============================================================================
   EDITION PILL — the sun/moon segmented switch.
   The same control the rest of labs.llc carries, at the same geometry: a 13px
   glyph with its size written on the <svg> tag as well as here, 2.5rem segments,
   sun always left and moon always right with the thumb moving to say which is
   live, and no text node inside a segment — the words are title + aria-label,
   so a page that never gets this sheet shows two glyphs rather than a sentence.
   ========================================================================== */
.mode-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    padding: 3px;
    border-radius: 9999px;
    border: 1px solid var(--line);
    background: rgba(var(--fg-rgb), 0.05);
    box-shadow: inset 0 1px 2px rgba(var(--shadow-rgb), 0.35);
}
.mode-pill__thumb {
    position: absolute;
    z-index: 0;
    top: 3px; bottom: 3px; left: 3px;
    width: calc(50% - 3px);
    border-radius: 9999px;
    background: linear-gradient(135deg, var(--accent-hi), var(--accent));
    box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.35);
    transition: transform 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
}
/* Which half is lit. Driven by a modifier on the container, not by a background
   on the segment — that is what lets it slide, and what stops two segments
   reading as lit at once mid-fade. */
.mode-pill--dark .mode-pill__thumb { transform: translateX(100%); }
/* Hover previews the switch. There are exactly two segments, so "the unlit one
   is hovered" already says which side the thumb belongs on. */
.mode-pill:has(.mode-pill__seg:not(.is-on):hover) .mode-pill__thumb { transform: translateX(100%); }
.mode-pill--dark:has(.mode-pill__seg:not(.is-on):hover) .mode-pill__thumb { transform: none; }

.mode-pill__seg {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.5rem;
    padding: 0.4rem 0.45rem;
    margin: 0;
    border: 0;
    border-radius: 9999px;
    background: none;
    color: var(--text-mute);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    /* Colour only. A background transition here is the bug that put two lit
       segments on screen at the same time. */
    transition: color 0.32s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.mode-pill__seg.is-on { color: var(--on-accent); cursor: default; }
/* Fallback where :has is missing and the thumb therefore cannot move: the unlit
   segment brightens in place rather than taking the thumb's colour. */
.mode-pill__seg:not(.is-on):hover { color: var(--accent-hi); }
.mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg.is-on { color: var(--text-mute); }
.mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg:hover { color: var(--on-accent); }
.mode-pill__seg:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 3px; }
/* 13px, and the same 13 is on the <svg> tag. An SVG with a viewBox and no
   dimensions falls back to 300x150 when no stylesheet reaches it. */
.mode-pill__i { width: 13px; height: 13px; flex: 0 0 auto; display: block; }

@media (prefers-reduced-motion: reduce) {
    .mode-pill__thumb { transition: none; }
}
@media (max-width: 640px) {
    .mode-pill__seg { min-width: 1.9rem; padding: 0.58rem 0.4rem; }
}
@media (max-width: 360px) {
    .mode-pill__seg { min-width: 1.7rem; }
}

/* Paper: the thumb is ink in a shallow well, the way it is on the main site. */
:root[data-theme="paper"] .mode-pill {
    background: linear-gradient(180deg, rgba(30,38,43,.045), rgba(30,38,43,.025));
    box-shadow: inset 0 1px 2px rgba(30, 38, 43, 0.055);
}
:root[data-theme="paper"] .mode-pill__thumb {
    background: var(--text);
    box-shadow: 0 1px 2px rgba(30,38,43,.26), 0 6px 18px rgba(30,38,43,.14);
}
:root[data-theme="paper"] .mode-pill__seg { color: var(--text-dim); }
:root[data-theme="paper"] .mode-pill__seg.is-on { color: #ffffff; }
:root[data-theme="paper"] .mode-pill__seg:not(.is-on):hover { color: var(--text); }
:root[data-theme="paper"] .mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg.is-on { color: var(--text-dim); }
:root[data-theme="paper"] .mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg:hover { color: #ffffff; }

/* =============================================================================
   PAPER — the handful of places a token swap alone cannot reach.
   Everything else in the hub is already themed by the tokens above.
   ========================================================================== */

:root[data-theme="paper"] body {
    font-family: var(--font-ui);
    background: var(--bg);
    color: var(--text);
}

/* The type inversion. Orbitron's job here was to shout; on paper the heading
   does its work by size and air instead, and the small tracked labels keep
   doing theirs. */
:root[data-theme="paper"] h1 {
    font-family: var(--font-display);
    font-weight: var(--display-weight);
    letter-spacing: var(--display-track);
    text-transform: var(--display-case);
    font-size: 1.9rem;
    text-shadow: none;
}
:root[data-theme="paper"] h1:active,
:root[data-theme="paper"] h1.clicked { text-shadow: none; }

/* Paths, sizes, code previews and the file grid stay monospaced — they are
   tabular data and the register does not ask them to change. */
:root[data-theme="paper"] .subtitle .path,
:root[data-theme="paper"] .file-info,
:root[data-theme="paper"] .project-btn .code-preview,
:root[data-theme="paper"] .project-btn .preview-content,
:root[data-theme="paper"] .search-input,
:root[data-theme="paper"] select,
:root[data-theme="paper"] button,
:root[data-theme="paper"] code,
:root[data-theme="paper"] pre {
    font-family: var(--font-mono);
}

/* The container is a sheet of paper, not a lit panel. */
:root[data-theme="paper"] .container {
    background: var(--bg);
    border: 1px solid var(--line);
    box-shadow: 0 1px 2px rgba(30, 38, 43, 0.06), 0 18px 48px rgba(30, 38, 43, 0.08);
}

/* The logo badge keeps the brand orange — it is a fill, not a letterform, and
   it is the one place the original colour still reads correctly on white. */
:root[data-theme="paper"] .logo-container img {
    filter: drop-shadow(0 1px 2px rgba(30, 38, 43, 0.18));
}
:root[data-theme="paper"] .logo-container .labs-mark {
    background: linear-gradient(135deg, #ff9526 0%, #f97316 45%, #e85d04 100%);
    color: #ffffff;
    box-shadow: 0 1px 2px rgba(30, 38, 43, 0.18), 0 6px 18px rgba(232, 93, 4, 0.20);
}

/* Buttons: accent fill, paper text. Scoped away from the two segmented controls
   — an element+attribute selector outweighs their single class, so an unscoped
   `button` rule here would have painted every pill segment as a toolbar button. */
:root[data-theme="paper"] button:not(.mode-pill__seg):not(.seg) {
    background: var(--accent);
    color: #ffffff;
    border-color: var(--accent);
    font-weight: 600;
}
:root[data-theme="paper"] button:not(.mode-pill__seg):not(.seg):hover {
    background: var(--accent-hi);
}
:root[data-theme="paper"] button.active:not(.mode-pill__seg):not(.seg) {
    background: var(--text);
    border-color: var(--text);
    box-shadow: none;
}
:root[data-theme="paper"] select,
:root[data-theme="paper"] .search-input {
    background: #ffffff;
    color: var(--text);
    border-color: var(--line-strong);
}
:root[data-theme="paper"] .search-input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(194, 65, 12, 0.12);
}

/* === SEGMENTED PILLS ON PAPER =============================================
   In the console each segment is a solid block of colour, because on black a
   fill is the only thing that reads. On stock, four saturated fills welded
   together is the loudest object on the page — so the pill inverts: one white
   track with hairline seams, and each segment says what it is in its own ink.
   The fill comes back on hover and on the segment that is genuinely primary.
   Same geometry, same seams, same group — only the weight changes. */
:root[data-theme="paper"] .seg-pill {
    border-color: var(--line-strong);
    background: #ffffff;
    box-shadow: 0 1px 2px rgba(30, 38, 43, 0.06), 0 4px 12px rgba(30, 38, 43, 0.07);
}
:root[data-theme="paper"] .seg-pill .seg {
    background: #ffffff;
    font-weight: 600;
}
/* The seam is a hairline of ink, not the console's black gap. */
:root[data-theme="paper"] .seg-pill .seg + .seg::before {
    background: var(--line);
    width: 1px;
}
/* On stock the chip goes deep enough for a white label to measure — 5.1:1 at
   the lighter end of the gradient. The neon green the console uses would be the
   loudest thing on a white page anyway. */
:root[data-theme="paper"] .seg-pill .seg-all {
    background: linear-gradient(135deg, #065f46 0%, #047857 100%);
    color: #ffffff;
}
:root[data-theme="paper"] .seg-pill .seg-edit  { background: #ffffff; color: var(--accent); }
:root[data-theme="paper"] .seg-pill .seg-admin { background: #ffffff; color: var(--text); }
:root[data-theme="paper"] .seg-pill .seg-next  { background: #be123c; color: #ffffff; }
/* Hover fills in place rather than brightening — there is nothing to brighten
   on white, which is why the console's filter trick had to be replaced here. */
:root[data-theme="paper"] .seg-pill .seg:hover { filter: none; color: #ffffff; }
:root[data-theme="paper"] .seg-pill .seg-all:hover   { background: #065f46; }
:root[data-theme="paper"] .seg-pill .seg-edit:hover  { background: var(--accent); }
:root[data-theme="paper"] .seg-pill .seg-admin:hover { background: var(--text); }
:root[data-theme="paper"] .seg-pill .seg-next:hover  { background: #9f1239; }
:root[data-theme="paper"] .seg-pill .seg:active { filter: none; opacity: 0.88; }

/* The version pill reads as a stamp on paper rather than a lit chip: hairline
   border, no halo, and the role colours taken down to where they measure. */
:root[data-theme="paper"] .version-pill {
    background: #ffffff;
    border-color: var(--line-strong);
    color: var(--accent);
    box-shadow: 0 1px 2px rgba(30, 38, 43, 0.07);
}
:root[data-theme="paper"] .version-pill:hover {
    background: var(--text);
    color: #ffffff;
    border-color: var(--text);
    box-shadow: 0 2px 8px rgba(30, 38, 43, 0.18);
    transform: none;
}
:root[data-theme="paper"] .version-pill.role-admin,
:root[data-theme="paper"] .version-pill.role-client { border-color: #047857; color: #047857; }
:root[data-theme="paper"] .version-pill.role-user   { border-color: #0e7490; color: #0e7490; }
:root[data-theme="paper"] .version-pill.role-admin:hover,
:root[data-theme="paper"] .version-pill.role-client:hover { background: #047857; border-color: #047857; color: #ffffff; }
:root[data-theme="paper"] .version-pill.role-user:hover   { background: #0e7490; border-color: #0e7490; color: #ffffff; }
:root[data-theme="paper"] .version-pill .role-badge {
    background: rgba(30, 38, 43, 0.04);
    border-color: currentColor;
}
:root[data-theme="paper"] .version-pill.role-admin .role-badge { background: rgba(4, 120, 87, 0.10); color: #047857; border-color: #047857; }
:root[data-theme="paper"] .version-pill.role-client .role-badge { background: rgba(185, 28, 28, 0.09); color: #b91c1c; border-color: #b91c1c; }
:root[data-theme="paper"] .version-pill.role-user .role-badge { background: rgba(14, 116, 144, 0.10); color: #0e7490; border-color: #0e7490; }
:root[data-theme="paper"] .version-pill .status-light { box-shadow: none; }

/* === PAPER LOGO ===========================================================
   The badge is an orange plate with the letterforms knocked out — designed to
   sit on black. prologo-paper.png is the same plate pressed in ink with the
   letterforms in stock. Both <img>s are in the markup and CSS picks one, so the
   right logo is on screen in the first frame rather than swapped in by script. */
/* Scoped through .logo-container, because pro.css sets `display:block` on
   `.logo-container img` — an element+class selector, which outweighs a lone
   class and left both badges on screen at once. */
.logo-container .logo-img--paper { display: none; }
:root[data-theme="paper"] .logo-container .logo-img--console { display: none; }
:root[data-theme="paper"] .logo-container .logo-img--paper { display: block; }
/* The drawn fallback, for a hub that has neither file on it. */
:root[data-theme="paper"] .logo-container .labs-mark {
    background: var(--text);
    color: #ffffff;
    box-shadow: 0 1px 2px rgba(30, 38, 43, 0.18), 0 6px 18px rgba(30, 38, 43, 0.14);
}

/* Cards. In the console every tile is filled with the accent; a grid of 40 rust
   tiles on white is a wall, so on paper they become stock with a hairline and
   the accent moves to the filename and the hover. */
:root[data-theme="paper"] .project-btn {
    background: #ffffff;
    color: var(--text);
    border: 1px solid var(--line);
    box-shadow: 0 1px 2px rgba(30, 38, 43, 0.05);
    font-weight: 500;
}
:root[data-theme="paper"] .project-btn:hover {
    border-color: var(--accent);
    box-shadow: 0 8px 22px rgba(30, 38, 43, 0.12);
}
:root[data-theme="paper"] .project-btn.folder { background: var(--surface-2); }
:root[data-theme="paper"] .project-btn.favorite { border-color: var(--accent); }
:root[data-theme="paper"] .project-wrapper.selected .project-btn {
    box-shadow: 0 0 0 2px var(--accent);
}
:root[data-theme="paper"] .project-btn .preview-name { color: var(--text); }

/* The thumbnail filenames carry a configurable glow — a halo that only reads on
   a dark tile. On stock it is a smear behind the one piece of text that has to
   be legible, so paper drops it and lets the ink do the work. The setting is
   left alone; it comes straight back in the console. */
:root[data-theme="paper"] .project-btn .preview-name { text-shadow: none !important; }


/* Code and browser previews: light stock, ink type, hairline chrome. Left on
   their console values these were navy plates with purple headings sitting in
   the middle of a white page. */
:root[data-theme="paper"] .project-btn .code-frame,
:root[data-theme="paper"] .project-btn .browser-frame,
:root[data-theme="paper"] .project-btn .preview-frame {
    background: var(--surface-1);
    border-color: var(--line);
}
:root[data-theme="paper"] .project-btn .code-header,
:root[data-theme="paper"] .project-btn .browser-bar {
    background: var(--surface-3);
    color: var(--text);
    border-bottom: 1px solid var(--line);
}
:root[data-theme="paper"] .project-btn .browser-bar .url { color: var(--text-mute); }
:root[data-theme="paper"] .project-btn .code-preview,
:root[data-theme="paper"] .project-btn .preview-content {
    background: transparent;
    color: var(--text-dim);
}
/* Syntax on paper: the same hues, taken down until each clears the floor at the
   0.57rem these previews are set in. */
:root[data-theme="paper"] .project-btn .syntax-php .keyword,
:root[data-theme="paper"] .project-btn .syntax-js .keyword   { color: #a21caf; }
:root[data-theme="paper"] .project-btn .syntax-php .function,
:root[data-theme="paper"] .project-btn .syntax-js .function,
:root[data-theme="paper"] .project-btn .syntax-css .property,
:root[data-theme="paper"] .project-btn .syntax-html .attr    { color: #1d4ed8; }
:root[data-theme="paper"] .project-btn .syntax-php .string,
:root[data-theme="paper"] .project-btn .syntax-js .string,
:root[data-theme="paper"] .project-btn .syntax-html .string,
:root[data-theme="paper"] .project-btn .syntax-json .string  { color: #047857; }
:root[data-theme="paper"] .project-btn .syntax-php .comment,
:root[data-theme="paper"] .project-btn .syntax-js .comment   { color: rgba(30, 38, 43, 0.66); }
:root[data-theme="paper"] .project-btn .syntax-php .variable,
:root[data-theme="paper"] .project-btn .syntax-css .string   { color: #a16207; }
:root[data-theme="paper"] .project-btn .syntax-html .tag,
:root[data-theme="paper"] .project-btn .syntax-json .key     { color: #c2410c; }
:root[data-theme="paper"] .project-btn .syntax-css .selector { color: #047857; }
:root[data-theme="paper"] .project-btn .syntax-md .header    { color: #6d28d9; }
:root[data-theme="paper"] .project-btn .syntax-md .bold      { color: #a16207; }

/* Notes, hearts and the menus. */
:root[data-theme="paper"] .notes-input,
:root[data-theme="paper"] .note {
    background: #ffffff;
    color: var(--text);
    border-color: var(--line);
}
:root[data-theme="paper"] #context-menu {
    background: #ffffff;
    border-color: var(--line);
    box-shadow: 0 2px 6px rgba(30,38,43,.10), 0 18px 40px rgba(30,38,43,.14);
}
:root[data-theme="paper"] #context-menu li { color: var(--text); }
:root[data-theme="paper"] #context-menu li:hover { background: var(--surface-2); }
:root[data-theme="paper"] #context-menu li.danger { color: var(--danger); }
:root[data-theme="paper"] .floating-delete-bar {
    background: #ffffff;
    border-color: var(--line);
    box-shadow: 0 2px 6px rgba(30,38,43,.10), 0 18px 40px rgba(30,38,43,.14);
}

/* Syntax previews sit on their own tinted stock rather than on black. */
:root[data-theme="paper"] .project-btn .css-frame  { background: #f2faf6; border-color: rgba(4, 120, 87, 0.35); }
:root[data-theme="paper"] .project-btn .js-frame   { background: #fdf9ef; border-color: rgba(161, 98, 7, 0.35); }
:root[data-theme="paper"] .project-btn .json-frame { background: #fdf6f0; border-color: rgba(194, 65, 12, 0.35); }
:root[data-theme="paper"] .project-btn .md-frame   { background: #f8f5fd; border-color: rgba(109, 40, 217, 0.35); }
:root[data-theme="paper"] .project-btn .text-frame { background: var(--surface-2); border-color: var(--line); }
:root[data-theme="paper"] .project-btn .syntax-md .code {
    background: rgba(30, 38, 43, 0.06);
    color: var(--ok);
}

/* Scrollbars and selection follow the stock. */
:root[data-theme="paper"] ::selection { background: rgba(194, 65, 12, 0.18); color: var(--text); }
:root[data-theme="paper"] ::-webkit-scrollbar-thumb { background: rgba(30, 38, 43, 0.24); }

/* =============================================================================
   LAB CONTROL — live status, active swatch, save
   ========================================================================== */

/* The lamp. Green means the panel is showing what is actually in force; the
   pulse is the same one the hub's other status lights use. */
/* Only ever shown on the open panel, where there is room — so it is set to be
   read across the room rather than squinted at: bigger, heavier, and on a chip
   of its own so it reads as a readout and not as a caption. */
.control-live {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 3px 10px 3px 8px;
    border-radius: 9999px;
    border: 1px solid rgba(var(--accent-rgb), 0.35);
    background: rgba(var(--accent-rgb), 0.10);
    color: var(--ok);
    font-size: 0.62rem;
    font-weight: 800;
    letter-spacing: 1.4px;
    white-space: nowrap;
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
}
:root[data-theme="paper"] .control-live {
    border-color: var(--line-strong);
    background: rgba(30, 38, 43, 0.04);
}
/* The colour actually in force, beside the words. */
.control-live__chip {
    width: 11px; height: 11px;
    border-radius: 2px;
    border: 1px solid rgba(var(--fg-rgb), 0.35);
    flex: 0 0 auto;
}
.control-live__dot {
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--ok);
    box-shadow: 0 0 7px var(--ok);
    flex: 0 0 auto;
    animation: controlLivePulse 2s ease-in-out infinite;
}
/* Amber when an artist theme is selected but a page theme is painting over it —
   the panel would otherwise show a lit swatch that is not what you are seeing. */
.control-live__dot.is-warn { background: var(--warn); box-shadow: 0 0 7px var(--warn); }
.control-live:has(.control-live__dot.is-warn) { color: var(--warn); }
@keyframes controlLivePulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { /* The colour actually in force, beside the words. */
.control-live__chip {
    width: 11px; height: 11px;
    border-radius: 2px;
    border: 1px solid rgba(var(--fg-rgb), 0.35);
    flex: 0 0 auto;
}
.control-live__dot { animation: none; } }

/* Which swatch you are on. The swatches carry their colour inline, so the
   marker cannot be a background — it is a ring outside the chip plus a lift,
   which reads on top of a gradient, a conic, or a flat fill alike. */
.swatch { position: relative; transition: transform 0.14s ease, box-shadow 0.14s ease; }
.swatch:hover { transform: translateY(-1px) scale(1.12); z-index: 2; }
.swatch.is-active {
    transform: translateY(-1px) scale(1.16);
    z-index: 3;
    box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 3.5px var(--accent), 0 0 9px rgba(var(--accent-rgb), 0.55);
}
/* A tick, so the active swatch is not signalled by colour alone. */
.swatch.is-active::after {
    content: '';
    position: absolute;
    left: 50%; top: 50%;
    width: 4px; height: 7px;
    margin: -5px 0 0 -2px;
    border-right: 2px solid var(--text-hi);
    border-bottom: 2px solid var(--text-hi);
    transform: rotate(42deg);
    filter: drop-shadow(0 0 2px rgba(var(--shadow-rgb), 0.9));
    pointer-events: none;
}
:root[data-theme="paper"] .swatch.is-active::after {
    border-color: #ffffff;
    filter: drop-shadow(0 0 2px rgba(30, 38, 43, 0.9));
}

/* SAVE. Quiet until you press it, then it says so. */
.control-save {
    flex-shrink: 0;
    padding: 3px 9px;
    border-radius: 9999px;
    border: 1px solid var(--accent);
    background: transparent;
    color: var(--accent);
    font-family: var(--font-display);
    font-size: 0.48rem;
    font-weight: 800;
    letter-spacing: 1.2px;
    cursor: pointer;
    line-height: 1;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.control-save:hover { background: var(--accent); color: var(--on-accent); }
.control-save.is-saved {
    background: var(--ok);
    border-color: var(--ok);
    color: var(--on-badge);
}
:root[data-theme="paper"] .control-save { border-color: var(--accent); color: var(--accent); }
:root[data-theme="paper"] .control-save:hover { background: var(--accent); color: #ffffff; }
:root[data-theme="paper"] .control-save.is-saved { background: var(--ok); border-color: var(--ok); color: #ffffff; }

/* The login screen's copy of the pill. SECURE sits top-right of the card, so
   this takes the top-left corner — the two balance and neither is in the way of
   the form. The card is position:relative already. */
.login-mode-pill {
    position: absolute;
    top: 12px;
    left: 14px;
    z-index: 5;
}
@media (max-width: 420px) {
    .login-mode-pill { top: 10px; left: 10px; }
}

/* The footer on the login card is the smallest type on the page and it was set
   at 45% ink — about 2.4:1 on stock. */
:root[data-theme="paper"] .login-container .hint { color: var(--text-mute); }
:root[data-theme="paper"] .login-container .hint span { opacity: 1; color: var(--text-faint); }

/* The border and the title's size live here rather than inline, so the two
   states can actually differ. Open is the original 2px lit edge; closed is a
   hairline. */
#mini-theme-panel { border: 2px solid var(--accent); }
#control-title { font-size: 0.69rem; letter-spacing: 2.5px; }

/* === MINIMISED CONTROL PANEL ==============================================
   Closed, this is a marker — it says the panel exists and where it is, nothing
   more. So it is a small rectangle with one hairline and no glow: no second
   border welded across it, no inner shadow, no lit edge. Everything that made
   it look like a shrunken window has been taken off rather than restyled.
   The class is put on by labPanelSetOpen, so none of this is decided in JS. */
#mini-theme-panel.is-collapsed {
    border-radius: 7px;
    border-width: 1px;
    padding: 0;
    /* The open panel's orange halo reads as an alert at this size. A flat,
       barely-there lift is enough to lift it off the page. */
    box-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.28) !important;
    background: var(--surface-1);
    opacity: 0.92;
    transition: opacity 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
#mini-theme-panel.is-collapsed:hover {
    opacity: 1;
    border-color: var(--accent);
    box-shadow: 0 2px 6px rgba(var(--shadow-rgb), 0.34) !important;
}
#mini-theme-panel.is-collapsed #control-header {
    background: transparent;
    border-bottom: 0;
    border-radius: 7px;
    padding: 0 9px;
    gap: 8px;
    height: 100%;
}
#mini-theme-panel.is-collapsed #control-title {
    font-size: 0.5rem;
    letter-spacing: 1.7px;
    font-weight: 700;
    text-shadow: none;                 /* the glow was the last console tell */
    /* The colour stays the live accent (set inline on the element): with the
       status hidden while closed, it is the only thing left saying which theme
       is running. */
}
#mini-theme-panel.is-collapsed #control-header-right { gap: 0; }
/* A chevron rather than a filled triangle — same affordance, less ink. */
#mini-theme-panel.is-collapsed #control-arrow {
    font-size: 0.55rem;
    line-height: 1;
    opacity: 0.55;
}
#mini-theme-panel.is-collapsed:hover #control-arrow { opacity: 0.95; }

/* Open, it is a panel again: square shoulders, a ruled header, room to work. */
#mini-theme-panel.is-open { border-radius: 10px; }
#mini-theme-panel.is-open #control-header { border-radius: 10px 10px 0 0; }

/* On paper the closed marker is a hairline chip on stock. */
:root[data-theme="paper"] #mini-theme-panel {
    border-color: var(--line-strong);
    background: #ffffff;
    box-shadow: 0 1px 2px rgba(30,38,43,.08), 0 10px 30px rgba(30,38,43,.12) !important;
}
:root[data-theme="paper"] #mini-theme-panel.is-collapsed {
    background: #ffffff;
    border-color: var(--line);
    box-shadow: 0 1px 2px rgba(30,38,43,.07) !important;
}
:root[data-theme="paper"] #mini-theme-panel.is-collapsed:hover {
    border-color: var(--accent);
    box-shadow: 0 2px 8px rgba(30,38,43,.11) !important;
}
:root[data-theme="paper"] #mini-theme-panel #control-header {
    background: transparent;
    border-bottom-color: var(--line);
}
:root[data-theme="paper"] #mini-theme-panel.is-open #control-header {
    background: var(--surface-2);
}
:root[data-theme="paper"] #control-title { text-shadow: none; }
