/*
 * Midijo | Eat. Discover. Connect.
 *
 * Developed by Kcode | Author: Obrempong
 */

/*
 * Midijo design tokens and component classes.
 *
 * Tailwind (loaded from the CDN in the layout) carries the utility layer; this
 * file holds the component classes that would be unreadable as long utility
 * strings.
 *
 * The palette is NOT defined here any more. It is generated per install from
 * the theme seeds by App\Support\ThemePalette and emitted as `--midijo-*`
 * custom properties by partials.theme, which loads ahead of this file. This
 * used to hold a third hand-written copy of the colours, alongside one in each
 * layout, and all three had drifted apart.
 *
 * The `--md-*` names below are kept as aliases onto those generated properties.
 * Every rule in this file already referenced them, so aliasing rather than
 * renaming makes the whole stylesheet theme-aware — and dark-mode-aware —
 * without touching the three hundred lines beneath.
 *
 * The generated properties hold space-separated channels (`255 248 246`), which
 * is what lets both Tailwind's opacity modifiers and the `/ 0.12` alphas in
 * this file work from the same value.
 */

:root {
    /* Colour — aliases onto the generated palette. */
    --md-primary: rgb(var(--midijo-primary));
    --md-on-primary: rgb(var(--midijo-on-primary));
    --md-primary-container: rgb(var(--midijo-primary-container));
    --md-on-primary-container: rgb(var(--midijo-on-primary-container));

    --md-secondary: rgb(var(--midijo-secondary));
    --md-on-secondary: rgb(var(--midijo-on-secondary));
    --md-secondary-container: rgb(var(--midijo-secondary-container));
    --md-on-secondary-container: rgb(var(--midijo-on-secondary-container));

    --md-surface: rgb(var(--midijo-surface));
    --md-surface-variant: rgb(var(--midijo-surface-variant));
    --md-surface-lowest: rgb(var(--midijo-surface-container-lowest));
    --md-background: rgb(var(--midijo-background));
    --md-on-surface: rgb(var(--midijo-on-surface));
    --md-on-surface-variant: rgb(var(--midijo-on-surface-variant));

    --md-outline: rgb(var(--midijo-outline));
    --md-outline-variant: rgb(var(--midijo-outline-variant));

    --md-error: rgb(var(--midijo-error));
    --md-on-error: rgb(var(--midijo-on-error));
    --md-error-container: rgb(var(--midijo-error-container));
    --md-on-error-container: rgb(var(--midijo-on-error-container));

    --md-warning: rgb(var(--midijo-warning));
    --md-warning-container: rgb(var(--midijo-warning-container));
    --md-on-warning-container: rgb(var(--midijo-on-warning-container));

    /* Spacing */
    --space-container: 24px;
    --space-gutter: 16px;
    --space-stack-sm: 8px;
    --space-stack-md: 16px;
    --space-stack-lg: 32px;
    --space-stack-xl: 48px;

    /*
     * Elevation.
     *
     * The shadow colour is a channel triple rather than a finished colour so
     * the alphas below can vary it. In light mode it borrows the page's ink,
     * which is what gives Midijo's cards a warm rather than a grey shadow.
     */
    --md-shadow-rgb: var(--midijo-on-surface);
    --md-shadow-card-alpha: 0.06;
    --md-shadow-card-alpha-2: 0.05;
    --md-shadow-raised-alpha: 0.10;
    --md-shadow-raised-alpha-2: 0.08;
    /*
     * Level 2 in the design language: a single wide, very faint pool rather
     * than the two-part cast above. This is what separates a panel from the
     * page without drawing a box around it, and it is why the social surfaces
     * read as floating paper instead of bordered containers.
     */
    --md-shadow-ambient-alpha: 0.04;

    --shadow-card:
        0 1px 2px rgb(var(--md-shadow-rgb) / var(--md-shadow-card-alpha)),
        0 4px 12px rgb(var(--md-shadow-rgb) / var(--md-shadow-card-alpha-2));
    --shadow-raised:
        0 2px 6px rgb(var(--md-shadow-rgb) / var(--md-shadow-raised-alpha)),
        0 12px 28px rgb(var(--md-shadow-rgb) / var(--md-shadow-raised-alpha-2));
    --shadow-ambient:
        0 4px 20px rgb(var(--md-shadow-rgb) / var(--md-shadow-ambient-alpha));
}

/*
 * Dark mode adjustments that are not colour-token swaps.
 *
 * Declared in the same three-state shape partials.theme uses — explicit choice
 * in both directions, then the device preference — because a rule that only
 * covered `prefers-color-scheme` would ignore a visitor who asked for dark on
 * a light-set device.
 *
 * Shadows go black and deepen. Borrowing the page ink works in light mode but
 * inverts in the dark, where `on-surface` is near-white: the cards would glow
 * instead of casting. And a shadow tuned for a white page is nearly invisible
 * against a near-black one, so the alphas roughly quadruple.
 */
:root[data-theme="dark"] {
    --md-shadow-rgb: 0 0 0;
    --md-shadow-card-alpha: 0.30;
    --md-shadow-card-alpha-2: 0.24;
    --md-shadow-raised-alpha: 0.44;
    --md-shadow-raised-alpha-2: 0.36;
    --md-shadow-ambient-alpha: 0.40;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --md-shadow-rgb: 0 0 0;
        --md-shadow-card-alpha: 0.30;
        --md-shadow-card-alpha-2: 0.24;
        --md-shadow-raised-alpha: 0.44;
        --md-shadow-raised-alpha-2: 0.36;
    --md-shadow-ambient-alpha: 0.40;
    }
}

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

/*
 * Typefaces come from the branding settings.
 *
 * These were hard-coded to Montserrat, and because this stylesheet loads after
 * the layout's inline block — same specificity, later wins — the heading font an
 * administrator chose on the branding screen was silently discarded. Reading
 * the custom property is what makes that setting take effect.
 */
body {
    font-family: var(--midijo-font-body, ui-sans-serif, system-ui, sans-serif);
}

h1, h2, h3, .font-display {
    font-family: var(--midijo-font-heading, Georgia, serif);
    letter-spacing: -0.01em;
}

h1 { font-size: 1.75rem; font-weight: 800; line-height: 1.2; }
h2 { font-size: 1.375rem; font-weight: 700; line-height: 1.25; }
h3 { font-size: 1.125rem; font-weight: 700; line-height: 1.3; }

.caption {
    font-size: 0.8125rem;
    color: var(--md-on-surface-variant);
}

.material-symbols-outlined {
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    vertical-align: middle;
    user-select: none;
}

.material-symbols-outlined.filled {
    font-variation-settings: 'FILL' 1;
}

/* -------------------------------------------------------------- Cards --- */

.md-card {
    background: var(--md-surface);
    border: 1px solid var(--md-outline-variant);
    border-radius: 16px;
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

.md-card--flat {
    box-shadow: none;
}

/*
 * A panel: the social shell's container.
 *
 * Distinct from `.md-card` on purpose, and the difference is the point of the
 * new look. `.md-card` sits on `surface` behind a full-strength hairline, which
 * is right for a dense admin table. A panel sits on the *lowest* surface — pure
 * white against the warm cream page — carries only a whisper of a border, and
 * is separated by the ambient pool instead. Content, not the container, is what
 * the eye lands on.
 *
 * That it reads `surface-container-lowest` rather than a literal white is what
 * makes it survive dark mode: the ramp inverts, the panel becomes the darkest
 * tone against a lighter page, and the same figure-and-ground relationship
 * holds rather than a white hole being punched in a dark screen.
 */
.md-panel {
    background: var(--md-surface-lowest);
    border: 1px solid rgb(var(--midijo-outline-variant) / 0.35);
    border-radius: 16px;
    box-shadow: var(--shadow-ambient);
}


/*
 * A panel with a brand edge along its top.
 *
 * The onboarding design marks the card a merchant is currently filling in with
 * a tangerine-to-emerald bar. Drawn as a pseudo-element rather than a real
 * child div so the markup stays a plain panel, and `overflow: hidden` on the
 * panel is what keeps the bar inside the 16px corner radius.
 */
.md-panel--edge {
    position: relative;
    overflow: hidden;
}

.md-panel--edge::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 6px;
    background: linear-gradient(to right, var(--md-primary), var(--md-secondary));
}

/* --------------------------------------------------------- Story ring --- */

/*
 * The gradient stroke that marks an unwatched story.
 *
 * Built as padding over a gradient background rather than as a `border-image`,
 * because a gradient border cannot follow a border-radius — it squares off at
 * the corners. The inner element paints the surface back over the middle,
 * leaving a ring, and the avatar sits inside that. Three nested elements is
 * simply what a round gradient outline costs.
 */
.story-ring {
    display: block;
    padding: 2px;
    border-radius: 999px;
    background: linear-gradient(45deg, var(--md-primary), var(--md-secondary));
}

.story-ring__inner {
    display: block;
    height: 100%;
    width: 100%;
    padding: 2px;
    border-radius: 999px;
    background: var(--md-surface-lowest);
}

.story-ring__inner > img {
    height: 100%;
    width: 100%;
    border-radius: 999px;
    object-fit: cover;
}

/*
 * Already watched. The ring stays — dropping it entirely makes the whole row
 * reflow as avatars change size — but goes flat and quiet, so the unwatched
 * ones are what the eye picks out.
 */
.story-ring--seen {
    background: var(--md-outline-variant);
}

/* ------------------------------------------------------------ Buttons --- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border-radius: 999px;
    padding: 12px 24px;
    font-weight: 600;
    font-size: 0.9375rem;
    line-height: 1;
    transition: filter 120ms ease, transform 120ms ease;
    cursor: pointer;
    border: 1px solid transparent;
}

.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* Visible focus ring — never remove this; keyboard users need it. */
.btn:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--md-primary);
    outline-offset: 2px;
}

.btn-primary {
    background: var(--md-primary);
    color: var(--md-on-primary);
}
.btn-primary:hover { filter: brightness(1.08); }

.btn-accent {
    background: var(--md-primary-container);
    color: var(--md-on-primary-container);
}

.btn-secondary {
    background: var(--md-secondary);
    color: var(--md-on-secondary);
}

.btn-outline {
    background: transparent;
    color: var(--md-primary);
    border-color: var(--md-outline-variant);
}
.btn-outline:hover { background: var(--md-surface-variant); }

.btn-ghost {
    background: transparent;
    color: var(--md-on-surface-variant);
}

.btn-danger {
    background: var(--md-error);
    color: var(--md-on-error);
}

/* ------------------------------------------------------------- Press --- */

/*
 * Haptic-feeling press, for the controls people tap repeatedly: like, save,
 * story tiles, rail navigation. The momentary give is the only confirmation
 * the tap registered before the network answers.
 *
 * Declared after the button variants, and that ordering is load-bearing:
 * `.btn:active` above lifts the button 1px, and the two selectors have equal
 * specificity, so whichever comes last wins. A `.btn.press` sitting earlier in
 * the file lost its squish and nudged instead. Do not move this block back up.
 *
 * The reduced-motion block at the foot of this file already collapses the
 * transition, so this needs no media query of its own.
 */
.press {
    transition: transform 120ms ease;
}

.press:active {
    transform: scale(0.96);
}



/* ------------------------------------------------------------ Drawers --- */

/*
 * The mobile navigation panel, shared by the admin console and the business
 * console.
 *
 * This started as `-translate-x-full peer-checked:translate-x-0
 * md:translate-x-0` on the aside, and it did not work: the checkbox's sibling
 * scrim appeared, but the panel stayed off-screen. `--tw-translate-x` computed
 * to 0px while the composed `transform` still read -100%, so the variant won
 * the variable and lost the declaration that consumes it — a Tailwind ordering
 * problem that cost nothing to write and left the drawer unopenable on every
 * phone.
 *
 * Written out here instead. Plain rules, no variant stack, no dependence on
 * which of two equal-specificity utilities the generator emitted last, and it
 * survives the move to a compiled build that the CDN setup is headed for.
 *
 * The contract is a checkbox carrying `.nav-drawer-toggle` somewhere before an
 * aside carrying `.nav-drawer`, as siblings; `~` is what makes this a
 * no-JavaScript disclosure. Each console keeps its own checkbox id for the
 * label's `for`, which is why this matches on a class and not an id.
 */
.nav-drawer {
    transform: translateX(-100%);
}

.nav-drawer-toggle:checked ~ .nav-drawer {
    transform: translateX(0);
}

/* From `md` up the panel is a static column and never translates at all. */
@media (min-width: 768px) {
    .nav-drawer,
    .nav-drawer-toggle:checked ~ .nav-drawer {
        transform: none;
    }
}

/* --------------------------------------------------------------- Chips -- */

.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    border: 1px solid var(--md-outline-variant);
    padding: 6px 14px;
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
}

.chip--active {
    background: var(--md-primary);
    border-color: var(--md-primary);
    color: var(--md-on-primary);
}

.chip--success {
    background: var(--md-secondary-container);
    border-color: transparent;
    color: var(--md-on-secondary-container);
}

/*
 * Both of these carried literal hex values, which meant they stayed pale amber
 * and pale pink on a dark page — light chips with light text, unreadable. They
 * now use the generated warning and error families, whose ink is contrast-
 * checked against its own container in both modes.
 */
.chip--warning {
    background: var(--md-warning-container);
    border-color: transparent;
    color: var(--md-on-warning-container);
}

.chip--danger {
    background: var(--md-error-container);
    border-color: transparent;
    color: var(--md-on-error-container);
}

/* -------------------------------------------------------------- Forms --- */

.field-label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--md-on-surface-variant);
    margin-bottom: 6px;
}

/*
 * The background was a literal #ffffff, which stayed white on a dark page and
 * put near-white text on it. It now tracks the lightest surface in the ramp,
 * which is white in light mode and the darkest tone in dark mode.
 *
 * The border was `outline-variant`, which measures 1.62:1 against the page —
 * below the 3:1 that WCAG 1.4.11 asks of a control's boundary. A field's edge is
 * how you know the field is there, so this uses `outline`, which the generator
 * holds to 3:1 in every preset. It reads slightly heavier than before; that is
 * the visible cost of the fix, and it is worth paying here. Decorative card
 * hairlines keep `outline-variant`.
 */
/*
 * Qualified by element name, and that is load-bearing rather than tidiness.
 *
 * Tailwind's forms plugin is injected by the CDN at runtime, so its stylesheet
 * always lands *after* this file. It styles text inputs through an attribute
 * list — `[type="text"], [type="email"], …` — which has exactly the same
 * specificity as a bare `.field-input`, so it won on document order and every
 * `<input>` in the app silently took the plugin's white fill and grey border
 * instead of these. That was invisible while this rule also said `#ffffff`;
 * under a dark theme it meant a white box with near-white text in it.
 *
 * `input.field-input` is one element-selector heavier than `[type="text"]`, so
 * it wins on specificity regardless of order. `select` and `textarea` were
 * never actually affected — the plugin matches those by element name, which
 * loses to a class — but they are qualified here too so the three do not drift
 * apart the next time the plugin changes. All 264 uses in the views are one of
 * these three elements.
 */
input.field-input,
select.field-input,
textarea.field-input {
    width: 100%;
    border-radius: 12px;
    border: 1px solid var(--md-outline);
    background: var(--md-surface-lowest);
    padding: 12px 14px;
    font-size: 0.9375rem;
    color: var(--md-on-surface);
}

input.field-input:focus,
select.field-input:focus,
textarea.field-input:focus {
    border-color: var(--md-primary);
    box-shadow: 0 0 0 3px rgb(var(--midijo-primary) / 0.18);
    outline: none;
}


/*
 * A field with a leading icon.
 *
 * The obvious way to write this is `class="field-input pl-10"`, and it does not
 * work: the rule above sets the `padding` shorthand under `input.field-input`
 * (specificity 0,1,1), which beats Tailwind's `.pl-10` (0,1,0) no matter what
 * order they load in. The icon then sits on top of the text. The header's
 * search box shipped like that.
 *
 * Matching the base rule's specificity is the fix. It also means the gap is
 * defined once, next to the padding it has to clear, instead of being a magic
 * number repeated at each call site.
 */
input.field-input--icon,
select.field-input--icon {
    padding-left: 2.5rem;
}

/*
 * A field on a white panel.
 *
 * `.field-input` fills with `surface-container-lowest`, which reads correctly
 * on the cream page but is invisible on the signed-out shell's white column —
 * white on white, separated only by a hairline. This flips the fill to the
 * page's warm tone, so the field still reads as a well to type into.
 */
input.field-input--tinted,
select.field-input--tinted,
textarea.field-input--tinted {
    background: rgb(var(--midijo-surface-container-low));
}

.field-error {
    margin-top: 6px;
    font-size: 0.8125rem;
    color: var(--md-error);
}

/* ------------------------------------------------------------ Layouts --- */

.stack-sm > * + * { margin-top: var(--space-stack-sm); }
.stack-md > * + * { margin-top: var(--space-stack-md); }
.stack-lg > * + * { margin-top: var(--space-stack-lg); }

.scroll-x {
    display: flex;
    gap: var(--space-gutter);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px;
}
.scroll-x::-webkit-scrollbar { display: none; }

/* --------------------------------------------------------- Reels view --- */

/*
 * The literal black and white below are deliberate and should stay literal.
 * These sit on top of video, not on a themed surface: letterboxing around a
 * clip is black in every theme, and a caption over footage needs white text
 * against a black scrim regardless of what the rest of the page is doing.
 * Theming them would make captions unreadable over bright video in light mode.
 */
.reel-stage {
    position: relative;
    background: #000;
    border-radius: 16px;
    overflow: hidden;
    aspect-ratio: 9 / 16;
    max-height: 80vh;
}

.reel-stage video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.reel-overlay {
    position: absolute;
    inset: auto 0 0 0;
    padding: 20px 16px;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent);
    color: #fff;
}

/*
 * A product pin sits on the video frame at a percentage position.
 *
 * The fill was a literal translucent white while the text used `on-surface`, so
 * in dark mode it became near-white text on near-white. Both now come from the
 * palette and stay a matched pair.
 */
.product-pin {
    position: absolute;
    transform: translate(-50%, -50%);
    background: rgb(var(--midijo-surface-container-lowest) / 0.94);
    color: var(--md-on-surface);
    border-radius: 999px;
    padding: 6px 12px;
    font-size: 0.8125rem;
    font-weight: 600;
    box-shadow: var(--shadow-raised);
    white-space: nowrap;
}

/* ------------------------------------------------------ Order timeline --- */

.timeline {
    position: relative;
    padding-left: 28px;
}

.timeline::before {
    content: '';
    position: absolute;
    left: 9px;
    top: 6px;
    bottom: 6px;
    width: 2px;
    background: var(--md-outline-variant);
}

.timeline-step {
    position: relative;
    padding-bottom: var(--space-stack-md);
}

.timeline-step::before {
    content: '';
    position: absolute;
    left: -24px;
    top: 4px;
    width: 12px;
    height: 12px;
    border-radius: 999px;
    background: var(--md-surface);
    border: 2px solid var(--md-outline-variant);
}

.timeline-step--done::before {
    background: var(--md-secondary);
    border-color: var(--md-secondary);
}

.timeline-step--current::before {
    background: var(--md-primary);
    border-color: var(--md-primary);
    /* Was a literal terracotta rgba, so it stayed orange whatever the theme. */
    box-shadow: 0 0 0 4px rgb(var(--midijo-primary) / 0.22);
}

/* ---------------------------------------------------------- Utilities --- */

.creator-tip {
    background: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
    border-radius: 16px;
    padding: 16px;
}

.empty-state {
    text-align: center;
    padding: var(--space-stack-xl) var(--space-container);
    color: var(--md-on-surface-variant);
}

/* Respect a user's reduced-motion preference. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
