/* ==========================================================================
   Listening surfaces: colour tokens, light and dark
   --------------------------------------------------------------------------
   The player and the offline page were the only dark things on a white site.
   A light wordmark on a black panel under a white storefront is what the owner
   reported, so the listening surfaces now have a theme and LIGHT IS THE DEFAULT.

   Scope is deliberate and narrow. Every token here is consumed by
   hipno-player.css and by the offline page's own <style> block, and by nothing
   else: the catalogue, the cart, the CMS pages, the support page and the
   account blocks are not themed and must not change.

   Two attributes drive this, both written by hipnoonline/player/theme-boot.phtml
   before anything paints:

     data-hipno-theme    the visitor's PREFERENCE - light | dark | system.
                         Drives the control's own state and nothing visual.
     data-hipno-scheme   the RESOLVED scheme - light | dark. Drives every colour.

   Resolving "system" in the boot script rather than in an @media block is what
   keeps the dark palette written down ONCE. The alternative - a
   [data-hipno-theme="system"] block repeated inside
   @media (prefers-color-scheme: dark) - means two hand-maintained copies of one
   list, and this repository has already paid for that: see the note in sw.js
   about the SHELL array and the parallel prefix list that drifted and left the
   offline page's logo precached and unreachable.

   Consequence, accepted knowingly: with JavaScript off neither attribute is
   written, so the visitor gets light whatever their operating system prefers.
   That is consistent with light being the default, and the controls hide
   themselves in that state rather than offering a button that cannot work.

   THE DARK COLUMN IS NOT A REDESIGN. Every dark value was lifted out of
   hipno-player.css and offline.phtml as they stood, so dark mode is the page
   exactly as it has always looked. If a value here differs from the one it
   replaced, that is a bug, not a decision.
   ========================================================================== */

/*
 * LIGHT, the default.
 *
 * .hipno-lib--light is in the selector list on purpose, and it is load bearing.
 * The account dashboard and the digital materials page put that class on the
 * library because those pages are white; they are out of scope here and must
 * keep rendering exactly as they do today. A declaration on the element itself
 * always beats a value inherited from :root, so pinning the light set on the
 * class is what stops a dark-theme visitor's account page coming out half dark.
 */
:root,
.hipno-lib--light {
    /* ---- brand ---- */
    /* The lime never flips. A lime pill with near-black type reads correctly on
       any surface, and flipping either half is how you get white type on pale
       lime. Same reasoning for the two artwork scrims near the bottom. */
    --hp-accent: #a8df00;
    --hp-accent-rgb: 168, 223, 0;
    --hp-on-accent: #11131a;
    /* Lime used as TEXT is a different problem from lime used as a fill: on
       white it measures 1.5:1 and is unreadable. So text gets its own token. */
    --hp-accent-ink: #4a5a20;

    /* ---- surfaces ---- */
    --hp-bg: #ffffff;
    --hp-bg-soft: #f2f5f8;
    --hp-bg-deep: #f7fafc;
    --hp-panel: #ffffff;
    --hp-surface-card: #ffffff;
    /* The card's artwork well is a separate token from --hp-bg-soft because the
       two were separate values before: #11131a here against #1b1e28 on the
       bar's thumbnail. Collapsing them would have changed dark mode. */
    --hp-surface-art: #f2f5f8;
    --hp-stage-bg: radial-gradient(circle at 50% 42%, #ffffff 0%, #eef2f6 70%);
    /*
     * The spiral keeps its dark disc in light mode.
     *
     * drawSpiral() strokes lime at 30-85% alpha and white at 5-17% straight onto
     * the canvas. On white the first washes out and the second is invisible.
     * Rather than teach the script to read tokens - a diff in a file another
     * workflow is editing, plus a getComputedStyle per frame - the wrap gets the
     * stage's old gradient, clipped round. The spiral then sits on the
     * background it was drawn for and reads as a deliberate focus object, the
     * way album art keeps its own colours in a light music player.
     */
    --hp-spiral-plate: radial-gradient(circle, #1b1e28 0%, #0a0b10 72%);

    /* ---- ink ---- */
    --hp-text: #1a202c;
    --hp-ink-hover: #1a202c;
    --hp-ink-soft: #4a5568;
    --hp-ink-mid: #4a5568;
    /* #5f6b7a, not the account page's #718096: that one is 4.02:1 on white and
       fails AA for normal text. See the pin block below, which keeps the account
       page on its existing value because that page is out of scope. */
    --hp-dim: #5f6b7a;
    /*
     * The same value as --hp-dim, and that is the measurement talking rather than
     * laziness. Dark has a third, dimmer step for the chooser's quietest text - the
     * section label, the filter placeholder, "nothing found" - and it already fails AA
     * there at 4.02:1 and 3.54:1. Light has NO ROOM for a third step: --hp-dim is
     * itself only 5.43:1 on white, and the placeholder sits on the filter's 5% veil,
     * which composites to #f4f4f4 and costs another half a point. #677386 measured
     * 4.36:1 there and failed; #5f6b7a measures 4.93:1 and passes.
     *
     * Kept as a separate token rather than deleted, for two reasons: dark must keep its
     * own value, and if the filter's fill is ever made plainer there is room to put a
     * genuine third step back here.
     */
    --hp-dimmer: #5f6b7a;
    /*
     * The preview badge ("Prévia de 45 segundos") needs its own ink, measured rather
     * than guessed. It is the one place where two light surfaces compound: the stage
     * gradient's outer stop at #eef2f6 with the badge's own 8% dark veil on top, which
     * composites to #dde1e6. --hp-dim on that is 4.14:1 and fails AA for 11.5px text;
     * #4a5568 is 5.73:1. In dark it is #9aa3b2, which is what the badge already was.
     */
    --hp-badge-ink: #4a5568;

    /* ---- lines ---- */
    --hp-line: #e6ebf1;
    --hp-line-soft: #edf2f7;
    --hp-line-strong: #cbd5e0;
    /* The decorative white veils - rails, hover fills, hairlines - are one
       channel triple with the alpha left at the call site, so every one of the
       sixteen keeps its own weight. */
    --hp-veil-rgb: 26, 32, 44;

    /* ---- controls ---- */
    --hp-knob: #1a202c;
    --hp-focus: #1a202c;

    /* ---- depth ---- */
    --hp-bar-shadow: 0 -6px 18px rgba(0, 0, 0, .10);
    --hp-panel-shadow: 0 18px 40px rgba(0, 0, 0, .14);
    --hp-card-shadow: 0 1px 3px rgba(0, 0, 0, .05);
    --hp-card-shadow-hover: 0 8px 20px rgba(0, 0, 0, .1);
    --hp-art-shadow: 0 8px 30px rgba(0, 0, 0, .25);
    --hp-play-shadow: 0 4px 12px rgba(0, 0, 0, .22);

    /* ---- over customer artwork, so theme-independent ---- */
    --hp-scrim: rgba(17, 19, 26, .78);
    --hp-scrim-soft: rgba(17, 19, 26, .72);
    --hp-scrim-ink: #f4f6f8;
    --hp-scrim-line: rgba(255, 255, 255, .22);
    --hp-scrim-line-strong: rgba(255, 255, 255, .45);

    /* ---- the offline page ---- */
    --off-bg: #f7fafc;
    --off-panel: #ffffff;
    --off-line: #e6ebf1;
    --off-ink: #1a202c;
    --off-muted: #5f6b7a;
    --off-green: #a8df00;
    --off-green-ink: #4a5a20;
    --off-green-hover: #b6ee10;
    --off-on-green: #0d0f14;
    --off-foot: #677386;
    --off-blue: #0094d9;
    /*
     * The wordmark's plate, and this is the fix the owner reported twice.
     *
     * logo.png is dark blue and green artwork drawn for a white page. On the dark
     * offline page the word HIPNO all but vanished, so it was given a white plate.
     * On a light page that plate is pure noise - a white card on a near-white
     * background with a shadow under it - and the mark belongs straight on the
     * surface it was drawn for.
     *
     * The plate's CHROME is what switches, not the element's display: hiding the
     * plate would hide the logo inside it, which is the opposite of the fix.
     */
    --off-plate-bg: transparent;
    --off-plate-pad: 0;
    --off-plate-shadow: none;
    --off-theme-color: #ffffff;
}

/*
 * color-scheme is SCOPED TO THE PLAYER, deliberately not put on :root.
 *
 * It tells the browser which way round a surface is, so the native widgets inside it
 * - the volume range above all - and its scrollbars follow the theme. On :root it
 * would do that for the WHOLE DOCUMENT: picking dark for the player would turn the
 * catalogue's scrollbars and every form control on the site dark, which is theming
 * the catalogue, and this task is scoped to the listening surfaces. Measured, not
 * assumed: with color-scheme on :root the browser's default text colour flipped on
 * elements outside the player too.
 *
 * The offline page is a listening surface end to end, so it sets its own :root value
 * in its own <style> block, where the rule can only ever apply to that page.
 */
.hipno-player { color-scheme: light; }
:root[data-hipno-scheme="dark"] .hipno-player { color-scheme: dark; }

/*
 * The account library keeps today's rendering, byte for byte.
 *
 * Nineteen per-property .hipno-lib--light .hl-* rules used to do this. They are
 * gone from hipno-player.css because the token set now covers all but these,
 * and these are the ones where the account page does NOT want the in-scope light
 * value:
 *
 *   --hp-dim          the page has shipped #718096 for its secondary text. It is
 *                     4.02:1 on white and fails AA, but fixing it would change a
 *                     page this task is scoped out of. Reported, not fixed.
 *   --hp-accent-ink   a playing track is blue there, not olive.
 *   --hp-focus        the play button's focus ring was never given a light value,
 *                     so it is white on these pages today.
 *   --hp-play-shadow  likewise: the heavier dark shadow is what ships.
 *   --hp-veil-rgb     the keep/forget hairlines are white veils there today.
 *
 * The last three are pre-existing debt rather than intent - a white focus ring on
 * a white card is invisible - and all three become correct by deleting a line
 * here, once somebody owns changing those pages.
 */
.hipno-lib--light {
    --hp-dim: #718096;
    --hp-accent-ink: #2b6cb0;
    --hp-focus: #fff;
    --hp-play-shadow: 0 4px 14px rgba(0, 0, 0, .4);
    --hp-veil-rgb: 255, 255, 255;
}

/* Two properties cannot be expressed as a token pin because the account page wants a
   different VALUE for the same token on different elements. Those rules stayed in
   hipno-player.css, beside the rules they override - this stylesheet is linked first,
   so an equal-specificity rule written here would lose the cascade to the player's. */

/*
 * DARK, declared once.
 *
 * Every value below was read out of the files it replaces. Nothing is invented,
 * and the test that matters is that a dark-mode screenshot is indistinguishable
 * from one taken before this file existed.
 */
:root[data-hipno-scheme="dark"] {
    --hp-accent: #a8df00;
    --hp-accent-rgb: 168, 223, 0;
    --hp-on-accent: #11131a;
    --hp-accent-ink: #a8df00;

    --hp-bg: #11131a;
    --hp-bg-soft: #1b1e28;
    --hp-bg-deep: #0d0f14;
    --hp-panel: #14171f;
    --hp-surface-card: rgba(255, 255, 255, .04);
    --hp-surface-art: #11131a;
    --hp-stage-bg: radial-gradient(circle at 50% 42%, #1b1e28 0%, #0a0b10 70%);
    --hp-spiral-plate: transparent;

    --hp-text: #f4f6f8;
    /* #fff, not #ffffff, so these are a literal match for the declarations they
       replaced - the dark column is meant to be greppable against the old file. */
    --hp-ink-hover: #fff;
    --hp-ink-soft: #cfd6e0;
    --hp-ink-mid: #b6bdc9;
    --hp-dim: #9aa3b2;
    /* 4.02:1 on the chooser panel. A pre-existing failure, kept because dark must
       not change; --hp-dimmer: #7d879a would make it 5.0:1 whenever that is wanted. */
    --hp-dimmer: #6f7887;
    --hp-badge-ink: #9aa3b2;

    --hp-line: rgba(255, 255, 255, .07);
    --hp-line-soft: rgba(255, 255, 255, .08);
    --hp-line-strong: rgba(255, 255, 255, .16);
    --hp-veil-rgb: 255, 255, 255;

    --hp-knob: #fff;
    --hp-focus: #fff;

    --hp-bar-shadow: 0 -6px 24px rgba(0, 0, 0, .35);
    --hp-panel-shadow: 0 18px 44px rgba(0, 0, 0, .55);
    --hp-card-shadow: none;
    --hp-card-shadow-hover: 0 8px 22px rgba(0, 0, 0, .3);
    --hp-art-shadow: 0 8px 40px rgba(0, 0, 0, .6);
    --hp-play-shadow: 0 4px 14px rgba(0, 0, 0, .4);

    --hp-scrim: rgba(17, 19, 26, .78);
    --hp-scrim-soft: rgba(17, 19, 26, .72);
    --hp-scrim-ink: #f4f6f8;
    --hp-scrim-line: rgba(255, 255, 255, .22);
    --hp-scrim-line-strong: rgba(255, 255, 255, .45);

    --off-bg: #0d0f14;
    --off-panel: #141821;
    --off-line: #232936;
    --off-ink: #f4f6f8;
    --off-muted: #9aa3b2;
    --off-green: #a8df00;
    --off-green-ink: #a8df00;
    --off-green-hover: #b6ee10;
    --off-on-green: #0d0f14;
    /* 4.17:1 on --off-bg. The other pre-existing dark failure; #7b8696 is 5.0:1. */
    --off-foot: #6c7686;
    --off-blue: #0094d9;
    --off-plate-bg: #fff;
    --off-plate-pad: 14px 20px;
    --off-plate-shadow: 0 10px 30px rgba(0, 0, 0, .35);
    --off-theme-color: #11131a;
}

/* ==========================================================================
   The controls
   ==========================================================================
   Both hide themselves until the boot script has written data-hipno-scheme. A
   theme switch that cannot switch anything is worse than no switch at all, and
   absence of the attribute means the script did not run.
   ========================================================================== */

/*
 * In the bar: ONE CYCLING BUTTON, light -> dark -> system -> light.
 *
 * Not a three-up segmented control, and the reason is written at length further
 * up hipno-player.css: 390px already cannot hold the artwork, the Solution's
 * name, the transport and the demo pill, and a segmented control there would
 * cost the track its title or force a fourth bar row. This costs 28px and
 * survives on a phone, which is the device somebody listens on in bed. The icon
 * shows the scheme in force and the aria-label names both the state and what
 * pressing it will do, so the cycle is not something to be discovered.
 */
.hipno-player .hp-theme {
    display: none;
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--hp-text);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    opacity: .7;
    transition: opacity .15s ease;
}

:root[data-hipno-scheme] .hipno-player .hp-theme { display: inline-flex; }

.hipno-player .hp-theme:hover { opacity: 1; }
.hipno-player .hp-theme:focus-visible {
    opacity: 1;
    outline: 2px solid var(--hp-focus);
    outline-offset: 2px;
}

.hipno-player .hp-theme svg {
    display: none;
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* The resolved scheme picks the icon; an explicit "system" preference overrides
   it with the half disc, because the point of that state is that it follows
   something else. The :not() clause is the no-JavaScript case. */
:root:not([data-hipno-scheme]) .hp-theme .hp-theme-ico--light,
:root[data-hipno-scheme="light"] .hp-theme .hp-theme-ico--light,
:root[data-hipno-scheme="dark"] .hp-theme .hp-theme-ico--dark { display: block; }

:root[data-hipno-theme="system"] .hp-theme .hp-theme-ico--light,
:root[data-hipno-theme="system"] .hp-theme .hp-theme-ico--dark { display: none; }
:root[data-hipno-theme="system"] .hp-theme .hp-theme-ico--system { display: block; }

/*
 * On the offline page: a THREE-STATE SEGMENTED CONTROL.
 *
 * There is room for it, it is self-describing, and this is the page somebody
 * arrives at with no connection and no appetite for working out what a cycling
 * icon does.
 */
.off-theme {
    display: none;
    margin: 20px 0 0;
    border: 1px solid var(--off-line);
    border-radius: 999px;
    overflow: hidden;
    vertical-align: middle;
}

:root[data-hipno-scheme] .off-theme { display: inline-flex; }

.off-theme button {
    margin: 0;
    padding: 7px 15px 6px;
    border: 0;
    background: none;
    color: var(--off-muted);
    font: inherit;
    font-size: .76rem;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.off-theme button + button { border-left: 1px solid var(--off-line); }

/* 11.68:1 in both themes, which is why the lime does not flip. */
.off-theme button[aria-pressed="true"] {
    background: var(--hp-accent);
    color: var(--hp-on-accent);
}

.off-theme button:focus-visible {
    outline: 2px solid var(--hp-focus);
    outline-offset: -2px;
}
