/*
 * Questrooms design tokens: the one place the system's values live.
 *
 * Loaded first on every public page (components/assets/css-head.blade.php) and on the standalone
 * rating page, so every other stylesheet only reads these. Two tiers:
 *
 *   1. Palette (--qr-palette-*): raw values. Stylesheets never read these directly; they exist so
 *      a role can be repointed without inventing a new colour.
 *   2. Roles (--qr-bg, --qr-mint, --qr-muted…): what a value is for. Components use only these.
 *
 * The same colours reach the e-mails through config/design.php; DesignTokensTest keeps the two in
 * step. The reference that explains each role is docs/questrooms-design-system.md.
 */

/* ---------- Typefaces ---------- */

/* Served from this site (public/fonts, OFL). Cabin is the variable cut, so 600 and 700 are real
   weights: with only the 400 file the browser drew every bold label, price and button as a
   smeared fake bold. The latin files carry å, ä, ö; latin-ext loads only if a page needs it. */
@font-face {
    font-family: 'Cabin';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('/fonts/cabin-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Cabin';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('/fonts/cabin-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Saira Stencil One';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/saira-stencil-one-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Saira Stencil One';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/saira-stencil-one-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    /* ---------- 1. Palette ---------- */

    /* OKLCH coordinates (L C H), so a new step is computed rather than eyeballed. The ground is
       blue-violet; the raised surfaces lean blue-teal, which is the site's look — a new surface
       keeps H ≈ 246, C ≈ 0.024 and steps L by 0.04–0.06. Mint's hover is the same hue ~0.056
       darker; a pressed or border step follows the same rule. #42dca3 and #0c111d are fixed. */
    --qr-palette-ink-950: #0c111d; /* 0.179 0.026 266.5 */
    --qr-palette-ink-900: #17212a; /* 0.242 0.022 246.1 */
    --qr-palette-ink-850: #1e2a35; /* 0.279 0.026 246.6 */
    --qr-palette-mint-500: #42dca3; /* 0.801 0.152 163.8 */
    --qr-palette-mint-600: #38c895; /* 0.745 0.142 164.5 */
    --qr-palette-on-mint: #0b0f0b;
    --qr-palette-white: #ffffff;
    --qr-palette-red-400: #ff6b6b;

    /* ---------- 2. Roles: colour ---------- */

    /* Depth comes from these three steps and a hairline, never from shadows. */
    --qr-bg: var(--qr-palette-ink-950);
    --qr-surface: var(--qr-palette-ink-900);
    --qr-surface-2: var(--qr-palette-ink-850);

    /* The one signal colour: action, live state, price. */
    --qr-mint: var(--qr-palette-mint-500);
    --qr-mint-hover: var(--qr-palette-mint-600);
    --qr-mint-soft: rgba(66, 220, 163, 0.12);
    --qr-on-mint: var(--qr-palette-on-mint);
    --qr-mint-wash: rgba(66, 220, 163, 0.06);
    --qr-mint-border: rgba(66, 220, 163, 0.4);
    --qr-link-underline: rgba(66, 220, 163, 0.6);

    --qr-text: var(--qr-palette-white);
    /* Long copy and captions laid over photos: a step brighter than muted. */
    --qr-soft: rgba(255, 255, 255, 0.82);
    --qr-muted: rgba(255, 255, 255, 0.64);
    /* 0.5, not 0.4: at 0.4 the 12px labels and placeholders fell to 3.6–3.8:1 on the three
       grounds, under WCAG AA's 4.5:1. 0.5 gives 4.8:1 on surface-2 and 5.3:1 on the page. */
    --qr-faint: rgba(255, 255, 255, 0.5);

    --qr-hairline: rgba(255, 255, 255, 0.1);
    --qr-hairline-strong: rgba(255, 255, 255, 0.2);
    /* Indicators that are "off": the unlit difficulty locks, the idle slideshow dots. */
    --qr-unlit: rgba(255, 255, 255, 0.25);

    --qr-danger: var(--qr-palette-red-400);
    --qr-danger-soft: rgba(255, 107, 107, 0.08);
    --qr-danger-border: rgba(255, 107, 107, 0.4);

    /* Behind modals and the scrolled navigation; panels sitting on photos. */
    --qr-scrim: rgba(12, 17, 29, 0.85);
    --qr-glass: rgba(12, 17, 29, 0.72);
    /* Shades that let white text sit on a photo: the hero, the audience tiles, the game banners. */
    --qr-shade-hero:
        linear-gradient(to top, rgba(12, 17, 29, 1) 0%, rgba(12, 17, 29, 0.55) 45%, rgba(12, 17, 29, 0.35) 100%),
        linear-gradient(to right, rgba(12, 17, 29, 0.85) 0%, rgba(12, 17, 29, 0.2) 70%);
    --qr-shade-bottom: linear-gradient(to top, rgba(12, 17, 29, 0.95) 10%, rgba(12, 17, 29, 0.15) 75%);
    --qr-shade-caption: linear-gradient(to top, rgba(12, 17, 29, 0.9), rgba(12, 17, 29, 0));
    /* The hero title's brushed-metal fill. */
    --qr-fill-title: linear-gradient(to bottom, #ffffff, #a0a0a0);

    /* The only shadow: menus and popovers that float over photos. */
    --qr-shadow-float: 0 16px 40px rgba(0, 0, 0, 0.4);

    /* Hover and "selected" for mint things. Never focus: at 18% it is too faint to find. */
    --qr-glow: 0 0 0 3px rgba(66, 220, 163, 0.18);

    /* ---------- States ---------- */

    /* Keyboard focus is always a solid 2px mint ring with a 2px gap (WCAG 2.4.13 asks for a 2px
       perimeter at 3:1). Three shapes of the same ring: an outline for anything that can take one;
       a box-shadow for places an outline cannot reach (a slider thumb, the span after a hidden
       input); and, on fields, one extra pixel outside the mint border. */
    --qr-focus-outline: 2px solid var(--qr-mint);
    --qr-focus-offset: 2px;
    --qr-focus-ring: 0 0 0 2px var(--qr-bg), 0 0 0 4px var(--qr-mint);
    --qr-focus-field: 0 0 0 1px var(--qr-mint);

    /* Layers laid over a surface on hover and press, so every component reacts alike. */
    --qr-state-hover: rgba(255, 255, 255, 0.08);
    --qr-state-pressed: rgba(255, 255, 255, 0.1);
    --qr-state-mint-hover: rgba(66, 220, 163, 0.1);
    --qr-disabled-opacity: 0.38;

    /* ---------- Motion ---------- */

    /* Motion is feedback, not decoration: it answers a hover, a press, a choice, a panel opening.
       Everyday UI uses the standard curve; enter/exit for things appearing and leaving; the
       expressive curve is kept for the one or two moments that deserve it (a confirmed booking).
       No bounce, no overshoot. */
    --qr-duration-instant: 100ms;
    --qr-duration-fast: 150ms;
    --qr-duration-base: 200ms;
    --qr-duration-slow: 320ms;
    --qr-duration-slower: 480ms;
    --qr-duration-scene: 800ms;
    /* One breath of the live-signal dot. */
    --qr-duration-pulse: 2400ms;

    --qr-ease-standard: cubic-bezier(0.2, 0, 0, 1);
    --qr-ease-enter: cubic-bezier(0, 0, 0.38, 0.9);
    --qr-ease-exit: cubic-bezier(0.2, 0, 1, 0.9);
    --qr-ease-expressive: cubic-bezier(0.4, 0.14, 0.3, 1);

    /* ---------- Type ---------- */

    --qr-display: 'Saira Stencil One', 'Helvetica Neue', Arial, sans-serif;
    --qr-body: 'Cabin', 'Helvetica Neue', Arial, sans-serif;

    /* Below the scale on purpose, for one place: three stat labels sharing a phone-width row
       in the account, where 12px wraps them onto two lines. Not for anything else. */
    --qr-text-micro: 10px;
    --qr-text-label: 12px;
    --qr-text-caption: 14px;
    --qr-text-button: 15px;
    --qr-text-body: 16px;
    --qr-text-lead: 18px;
    --qr-text-subheading: 20px;
    --qr-text-heading-sm: 22px;
    --qr-text-heading: 24px;
    --qr-text-data: 28px;
    --qr-text-section-title: clamp(32px, 5vw, 40px);
    --qr-text-page-title: clamp(30px, 5vw, 48px);

    --qr-tracking-label: 0.12em;
    --qr-tracking-display: 0.02em;

    /* ---------- Space: a 4px step on the 8px grid ---------- */

    --qr-space-1: 4px;
    --qr-space-2: 8px;
    --qr-space-3: 12px;
    --qr-space-4: 16px;
    --qr-space-5: 24px;
    --qr-space-6: 32px;
    --qr-space-7: 48px;
    --qr-space-8: 64px;

    --qr-wrap: 1200px;
    --qr-wrap-narrow: 820px;
    --qr-gutter: 16px;
    /* Height of the promo bar above the navigation; the bar's script sets it once it knows. */
    --qr-announce-h: 0px;

    /* ---------- Shape ---------- */

    /* Checkboxes and other controls under 24px, where 12px would make a circle. */
    --qr-radius-small: 6px;
    --qr-radius-card: 12px;
    --qr-radius-panel: 16px;
    --qr-radius-pill: 9999px;

    /* ---------- Layers ---------- */

    --qr-layer-raised: 10;
    --qr-layer-sticky: 30;
    --qr-layer-modal: 2000;
    /* SweetAlert opens on top of the booking modal. */
    --qr-layer-alert: 2100;
}

/* Moving between pages of the site cross-fades instead of flashing white. Only the whole page
   fades: no element is given a view-transition-name — a card photo "flying" into the hero of its
   game page glitched when the two photos were cropped differently or not yet loaded. Browsers
   without cross-document view transitions simply navigate as before. */
@view-transition {
    navigation: auto;
}

::view-transition-group(*) {
    animation-duration: var(--qr-duration-slow);
    animation-timing-function: var(--qr-ease-standard);
}

/* Someone who asked their system for less motion gets none: every transition and animation on
   the site ends at once instead of playing. The one place !important is right — it has to beat
   every component's own timing. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    @view-transition {
        navigation: none;
    }

    /* The one exception: a loader that stops would read as "stuck" while a payment is sent. It
       turns slowly instead — a status, not motion for its own sake. */
    .qr-spin {
        animation-duration: 1600ms !important;
        animation-iteration-count: infinite !important;
    }
}
