/* =====================================================================
 * Been There: shared stylesheet
 * Loaded by every page (index, privacy, terms, support).
 * Page-specific styles remain inline in each HTML file.
 * ===================================================================== */

/* ===== RESET ===== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

/* ===== DESIGN TOKENS ===== */
:root {
    /* Brand purple: mirrors app Colors.ts */
    --purple-primary: #6B46C1;
    --purple-80: #7C5ACE;
    --purple-60: #9F7AEA;
    --purple-40: #C3B1E1;
    --purple-20: #D9CEF0;
    --purple-10: #EAE5F7;
    --purple-5: #F5F2FB;
    --purple-pressed: #5A3BA8;
    --purple-deep: #44337A;

    /* Surfaces */
    --bg-primary: #F5F5F5;
    --bg-secondary: #F5F3F8;
    --card: #FCFCFC;

    /* Text */
    --text-primary: #121212;
    --text-secondary: #8C8C8C;
    --text-disabled: #C2C2C2;
    --white: #FFFFFF;

    /* Category colors: match app PlaceCategory */
    --cat-restaurant: #1CC05B;
    --cat-bar: #E537CE;
    --cat-cafe: #37BDE5;
    --cat-pub: #E75F10;

    /* Sentiment colors: mirror app SentimentChip mapping
       (semantic.topSpot / semantic.statusSuccess / semantic.statusError) */
    --sentiment-top-spot: #A855F7;
    --sentiment-recommend: #10B981;
    --sentiment-not-for-me: #DC2626;

    /* Fonts */
    --font-heading: 'Manrope', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-body: 'Work Sans', -apple-system, BlinkMacSystemFont, sans-serif;

    /* Radius */
    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-std: 16px;
    --radius-lg: 20px;
    --radius-xl: 24px;
    --radius-pill: 100px;

    /* Shadows */
    --shadow-subtle: 0 2px 4px rgba(107, 70, 193, 0.08);
    --shadow-elevated: 0 12px 28px rgba(107, 70, 193, 0.10);

    /* Store badges: width of one button. Height derives from it, so this is
       the only number to change. Any container can override it. */
    --badge-w: 160px;
}

/* ===== STORE BADGES =====
 * Both badges render as the same box: --badge-w by --badge-h, identical bars.
 *
 * This is a deliberate exception to the brand guidelines, decided by Jamie on
 * 2026-07-31, and worth understanding before touching it. The two pieces of
 * artwork are different shapes. Apple's PNG is 479x160, a ratio of 2.994;
 * Google's bar is 564x168, a ratio of 3.357. They cannot share a box unless
 * one of them is stretched, and stretching is the one thing both Apple's and
 * Google's badge licences prohibit.
 *
 * Matching on height (Play 11% longer) and matching on width (App Store bar
 * 12% thicker) were both built and both rejected: a pair of unequal bars
 * offering the same thing to different users read as a bug.
 *
 * So the box is set to Apple's own ratio, which leaves Apple's artwork
 * untouched, and Google's bar is stretched about 12% vertically to fill it.
 * All of the distortion lands on the Google badge, none on Apple's. If Google
 * ever objects, delete the height on the two img rules below and restore
 * `width: auto` on the play badge: that reverts to matched height with no
 * other change.
 *
 * Google's PNG bakes 41px of clear space around the bar on a 646x250
 * artboard. The img is oversized by the artboard ratio and the clear space
 * pulled back out with negative margin, so the bar lands at exactly
 * --badge-w by --badge-h and the gap between badges is the spacing set.
 *
 * Both badges are PNG. Apple only publishes SVG, and an SVG that fails to load
 * takes the primary CTA down with it, so it is rasterised at build time by
 * scripts/app-store-badge-png.mjs.
 *
 * The colour and text-decoration are the graceful-degradation path: if either
 * image fails, the alt text reads as legible white copy rather than a default
 * underlined link, which is close to invisible on the purple.
 */
.store-badge {
    /* Apple's PNG ratio, so its artwork fills the box at its natural shape. */
    --badge-h: calc(var(--badge-w) * 160 / 479);
    display: flex;
    width: var(--badge-w);
    height: var(--badge-h);
    color: var(--white);
    text-decoration: none;
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 15px;
    transition: transform 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.store-badge:hover { transform: translateY(-2px); }
.store-badge:active { transform: translateY(0); }

/* Both dimensions set, so the default object-fit of `fill` stretches rather
   than preserving the ratio. That is the intended behaviour here. */
.store-badge img {
    width: var(--badge-w);
    height: var(--badge-h);
    display: block;
}

.store-badge--play img {
    width: calc(var(--badge-w) * 646 / 564);
    height: calc(var(--badge-h) * 250 / 168);
    margin: calc(var(--badge-h) * -41 / 168) calc(var(--badge-w) * -41 / 564);
}

/* Side by side the pair needs width * 2 + 12px of gap. At 160px that is 332px
   against the 335px a 375px phone offers, which fits but leaves nothing for a
   360px screen. 148px brings it to 308px and clears both. */
@media (max-width: 480px) {
    :root { --badge-w: 148px; }
}

/* ===== BASE ===== */
html { scroll-behavior: smooth; }

body {
    font-family: var(--font-body);
    color: var(--text-primary);
    line-height: 1.6;
    background: var(--white);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* ===== HEADER =====
 * Default state: transparent (used on landing over purple hero).
 * .scrolled state: solid white with blur (used on landing after scroll,
 *                  and on every secondary page from page-load).
 */
.header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    padding: 20px 32px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.header.scrolled {
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    box-shadow: var(--shadow-subtle);
    padding: 12px 32px;
}

.logo {
    font-family: var(--font-heading);
    font-size: 22px;
    font-weight: 700;
    color: var(--white);
    text-decoration: none;
    letter-spacing: -0.5px;
    transition: color 0.35s ease;
}

.header.scrolled .logo { color: var(--purple-primary); }

.header-links a {
    font-family: var(--font-heading);
    color: rgba(255, 255, 255, 0.8);
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
    transition: color 0.35s ease;
}

.header.scrolled .header-links a { color: var(--text-secondary); }
.header-links a:hover { opacity: 0.7; }
.header.scrolled .header-links a:hover { color: var(--purple-primary); opacity: 1; }

/* ===== FOOTER ===== */
.footer {
    background: #0D0D14;
    padding: 32px 24px;
}

.footer-inner {
    max-width: 1060px;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
}

.footer-left {
    display: flex;
    align-items: center;
    gap: 12px;
}

.footer-logo { width: 32px; height: 32px; border-radius: var(--radius-sm); }

.footer-brand {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 16px;
    color: white;
}

.footer-right {
    display: flex;
    align-items: center;
    gap: 24px;
    flex-wrap: wrap;
}

.footer-right a {
    font-family: var(--font-body);
    color: rgba(255, 255, 255, 0.45);
    text-decoration: none;
    font-size: 13px;
    transition: color 0.25s;
}

.footer-right a:hover { color: rgba(255, 255, 255, 0.75); }

.footer-copy {
    width: 100%;
    text-align: center;
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
    font-family: var(--font-body);
    font-size: 11px;
    color: rgba(255, 255, 255, 0.25);
}

/* ===== UTILITIES ===== */

/* Skip-to-content link, visible on focus */
.skip-link {
    position: absolute;
    top: -100px;
    left: 16px;
    z-index: 1000;
    padding: 12px 20px;
    background: var(--purple-primary);
    color: white;
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 14px;
    border-radius: var(--radius-sm);
    text-decoration: none;
    transition: top 0.2s ease;
}

.skip-link:focus { top: 16px; }

/* ===== RESPONSIVE ===== */
@media (max-width: 768px) {
    .header { padding: 16px 20px; }
    .header.scrolled { padding: 12px 20px; }

    .footer-inner { justify-content: center; text-align: center; }
    .footer-left { justify-content: center; }
}

/* ===== REDUCED MOTION =====
 * Respect user OS setting to disable decorative animations.
 * Does not affect essential transitions under 100ms (too short to feel).
 */
@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;
    }
}

/* ===== IN-APP BROWSER NOTICE =====
 * Built by public/store-link.v4.js when the App Store is unreachable from the
 * browser the visitor is stuck in.
 *
 * A full-screen takeover rather than a bar along the bottom, for two reasons.
 * Step one is an arrow aimed at the ⋯ in the host app's chrome, which sits
 * above our viewport, so it has to reach the top of the screen to point at
 * anything. And on /get the page underneath is two store badges that do nothing
 * here, so leaving them visible only offers a tap that fails.
 *
 * Deliberately no card. The only white on the screen is the picture of their
 * menu, which is the one thing they are looking for.
 */
.iab-notice {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    flex-direction: column;
    padding: 0 22px calc(18px + env(safe-area-inset-bottom, 0px));
    background: linear-gradient(150deg, #3B2C6B 0%, var(--purple-primary) 60%, var(--purple-80) 100%);
    /* Last resort on a screen too short for the arrow and the steps together:
       scroll rather than clip the instruction off the bottom. */
    overflow-y: auto;
}

/* Step one: the arrow and its label share a block, so the label sits inside the
   sweep of the arrow rather than beside it. */
.iab-notice__aim {
    position: relative;
    /* Tall enough that the menu picture below clears the host app's own menu,
       which drops to roughly 318px into the page area. */
    height: 300px;
    flex: none;
}

/* Head offset past the container's right padding to line up with the button
   itself, which sits about 36px in from the edge of the screen. */
.iab-notice__arrow {
    position: absolute;
    top: 2px;
    right: -20px;
    color: var(--white);
}

/* Draws itself in, holds, then restarts. On a screen whose entire job is
   pointing at one corner, the motion is the instruction. */
.iab-notice__stroke {
    stroke-dasharray: 340;
    animation: iab-notice-draw 3.4s ease-in-out infinite;
}

@keyframes iab-notice-draw {
    0% { stroke-dashoffset: 340; }
    28%, 82% { stroke-dashoffset: 0; opacity: 1; }
    92% { stroke-dashoffset: 0; opacity: 0; }
    93%, 100% { stroke-dashoffset: 340; opacity: 0; }
}

.iab-notice__aim .iab-notice__step {
    position: absolute;
    top: 168px;
    left: 0;
}

.iab-notice__step {
    display: flex;
    align-items: center;
    gap: 11px;
    margin: 0;
    font-family: var(--font-heading);
}

.iab-notice__step b {
    font-weight: 700;
    font-size: 24px;
    letter-spacing: -0.4px;
    color: var(--white);
}

.iab-notice__num {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--white);
    color: var(--purple-primary);
    font-family: var(--font-heading);
    font-weight: 800;
    font-size: 15px;
}

/* A picture of their menu, not a control. The rows they do not want are dimmed
   and the one they do is lifted onto white, so it is matched by shape rather
   than read: the label varies with the visitor's default browser and cannot be
   predicted from here. Indented to the width of the step number above it so it
   reads as belonging to step two. */
.iab-notice__menu {
    margin: 14px 0 0 39px;
    padding: 6px 0;
    background: #E7DEF8;
    border-radius: 14px;
    box-shadow: 0 10px 26px rgba(25, 10, 55, 0.22);
}

.iab-notice__mrow {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 15px;
    font-family: var(--font-body);
    font-size: 13.5px;
    color: #3A3A3A;
    opacity: 0.45;
}

.iab-notice__mrow--hit {
    margin: 2px 6px;
    padding: 10px 12px;
    border-radius: 9px;
    background: var(--white);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10);
    font-weight: 700;
    color: var(--text-primary);
    opacity: 1;
}

.iab-notice__mrow svg {
    flex: none;
}

.iab-notice__foot {
    margin-top: auto;
    padding-top: 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.iab-notice__brand {
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 14px;
    color: var(--white);
}

.iab-notice__brand img {
    border-radius: 7px;
}

/* Only rendered where dismissing leads somewhere: see store-link.v4.js. */
.iab-notice__close {
    padding: 10px 4px;
    font-family: var(--font-body);
    font-size: 13.5px;
    color: rgba(255, 255, 255, 0.6);
    background: none;
    border: none;
    cursor: pointer;
}

/* Answers a badge tap the in-app browser was always going to swallow. */
.iab-notice--pulse .iab-notice__menu {
    animation: iab-notice-pulse 600ms ease;
}

@keyframes iab-notice-pulse {
    0%, 100% { transform: scale(1); }
    35% { transform: scale(1.04); }
}

/* Short screens cannot afford the full arrow. Scaled to keep its ratio, which
   walks the head a little left of the button: a small loss of aim, against the
   steps being pushed off the bottom of the screen. */
@media (max-height: 700px) {
    .iab-notice__aim { height: 210px; }
    .iab-notice__arrow { width: 153px; height: 210px; }
    .iab-notice__aim .iab-notice__step { top: 118px; }
}

@media (prefers-reduced-motion: reduce) {
    .iab-notice__stroke { animation: none; stroke-dashoffset: 0; }
    .iab-notice--pulse .iab-notice__menu { animation: none; }
}

/* The explanation the visual version drops entirely. A listener gets neither
   the arrow nor the picture of the menu, so the sentence survives for them. */
.iab-notice__sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}
