/* =====================================================================
   ym-polish.css - the site-wide "feel" layer.

   Loaded by base.html straight after Bootstrap and Font Awesome, BEFORE
   base.html's own <style> and before every page's <style> block. That order
   is deliberate: anything a page already designs for itself still wins, so
   this file can only refine what is shared (the bar, menus, dialogs, form
   fields, buttons, focus, motion) and never re-styles a page behind its back.
   The few rules that MUST beat a page rule say so and use `:root` for the
   extra specificity instead of !important.

   The principles behind every value here (Apple's Human Interface
   Guidelines and the WWDC "Designing Fluid Interfaces" talk, translated for
   the web):

     * Respond on press, not on release - a control reacts the instant it is
       touched (scale on :active), so a tap never feels like it was missed.
     * Animate only transform and opacity. Both run on the compositor; width,
       height, padding or font-size changes re-lay out the page on every frame
       and that is what reads as jitter on an iPad or a phone.
     * One family of curves everywhere, so every surface moves the same way.
       No overshoot on things that simply appear (a menu, a dialog) - bounce
       is only honest after a physical throw, and nothing here is thrown.
     * Solid surfaces, no live blur. Frosted glass (backdrop-filter) was
       tried and removed: the blur is recomputed on every scroll frame, which
       made scrolling heavier on phones, and it washed the brand navy out.
     * Nothing that contains text is ever SCALED while it appears. Scaling
       re-draws every letter and icon on every frame, which reads as words
       shimmering or jittering; popups fade with a few pixels of slide.
     * Respect the device: safe areas (notch / home indicator), 44px touch
       targets, no zoom-on-focus on iPhone, no sticky hover on touch screens,
       reduced motion and reduced transparency honoured.

   Deliberately NOT used (see accounts/test_landing_cards.py for the history):
   will-change, translateZ / translate3d, backface-visibility. On the real
   iPads and phones those compositing tricks made the landing page jitter more,
   not less.
   ===================================================================== */


/* ---------------------------------------------------------------------
   1. TOKENS
   --------------------------------------------------------------------- */
:root {
    /* Colours: all in ym-theme.css (light and dark). This file only adds
       motion, shape and elevation. */

    /* Curves.
       out    - things arriving or reacting: fast start, long soft settle.
       sheet  - the curve iOS uses for sheets and popovers; critically damped,
                so it settles without overshoot.
       inout  - something moving from one resting place to another. */
    --ym-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --ym-ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
    --ym-ease-inout: cubic-bezier(0.65, 0, 0.35, 1);

    /* Durations. Short on purpose: an interface that waits on its own
       animations feels slow, however pretty the animation is. */
    --ym-dur-press: 90ms;
    --ym-dur-1: 160ms;
    --ym-dur-2: 240ms;
    --ym-dur-3: 360ms;

    /* Elevation - two soft layers each (a tight contact shadow plus a wide
       ambient one) reads as real depth; one big blurry shadow reads as smudge. */
    --ym-shadow-1: 0 1px 2px rgba(16, 24, 40, 0.05), 0 1px 3px rgba(16, 24, 40, 0.06);
    --ym-shadow-2: 0 2px 6px -1px rgba(16, 24, 40, 0.06), 0 8px 24px -4px rgba(16, 24, 40, 0.10);
    --ym-shadow-3: 0 4px 10px -2px rgba(16, 24, 40, 0.08), 0 24px 48px -12px rgba(16, 24, 40, 0.22);

    --ym-hairline: var(--ym-line);
    --ym-focus-ring: 0 0 0 4px rgba(52, 152, 219, 0.28);

    /* Bootstrap reads its radii from these variables, so one change here
       gives every card, field, alert, button, dropdown and dialog the same,
       slightly softer family of corners (10 / 8 / 14 / 20 px). */
    --bs-border-radius: 0.625rem;
    --bs-border-radius-sm: 0.5rem;
    --bs-border-radius-lg: 0.875rem;
    --bs-border-radius-xl: 1.25rem;

    /* Dialog scrim: a deep navy instead of pure black, a touch lighter. */
    --bs-backdrop-bg: #0b1218;

    /* Text selection in the brand blue instead of the OS default. */
    accent-color: var(--ym-accent);
}


/* ---------------------------------------------------------------------
   2. TYPE & RENDERING
   --------------------------------------------------------------------- */
html {
    -webkit-tap-highlight-color: transparent;   /* the grey iOS tap flash; :active gives real feedback below */
}
body {
    -webkit-font-smoothing: antialiased;        /* macOS / iOS: the thinner, crisper rendering Apple's own pages use */
    -moz-osx-font-smoothing: grayscale;
    font-kerning: normal;
}
::selection { background: rgba(52, 152, 219, 0.22); }

/* Headings break into even lines instead of leaving one orphan word alone
   on the last line. Pure line-breaking - no size or spacing changes, and
   browsers without support ignore it. Deliberately NOT applied to paragraphs:
   the reading passages are numbered line by line, and their wrapping must
   stay exactly what the exam screens were built and tested with. */
h1, h2, h3, h4, .display-1, .display-2, .display-3, .display-4, .display-5, .display-6 { text-wrap: balance; }


/* ---------------------------------------------------------------------
   3. LAYOUT - sticky footer
   The footer sat in the middle of the screen on short pages (an empty
   notebook, a 404) with the background showing under it. Body is a column
   and the content area takes the spare height, so the footer always rests
   on the bottom edge. Block children of a column flex box still stretch to
   full width, and .container still centres itself with auto margins.
   --------------------------------------------------------------------- */
body {
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
}
body > .main-content { flex: 1 0 auto; width: 100%; }
body > footer { flex-shrink: 0; }


/* ---------------------------------------------------------------------
   4. NAVBAR
   Solid brand navy (#1a252f, set in base.html), exactly the colour Safari's
   own toolbar is tinted with (theme-color), so the two read as one surface.
   A hairline plus a soft shadow separates it from the page.
   --------------------------------------------------------------------- */
.navbar {
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 6px 20px -8px rgba(0, 0, 0, 0.25) !important;
}

/* Brand: the cap icon tilts a little on hover - a small "alive" detail. */
.navbar-brand i { display: inline-block; transition: transform var(--ym-dur-3) var(--ym-ease-out); }
.navbar-brand:hover i { transform: rotate(-12deg); }

/* Hamburger: a calm rounded square with a pressed state, not Bootstrap's
   heavy focus glow. */
.navbar-toggler {
    border: 1px solid rgba(255, 255, 255, 0.14) !important;
    border-radius: 10px !important;
    transition: background-color var(--ym-dur-1) ease, transform var(--ym-dur-1) var(--ym-ease-out);
}
.navbar-toggler:focus { box-shadow: none; }
.navbar-toggler:focus-visible { box-shadow: 0 0 0 3px rgba(243, 156, 18, 0.55); }
.navbar-toggler[aria-expanded="true"] { background-color: rgba(255, 255, 255, 0.10); }
.navbar-toggler:active { transform: scale(0.94); }

.nav-icon-btn:active, .navbar .dropdown-toggle:active .user-avatar { transform: scale(0.92); }
.nav-icon-btn { transition: background-color var(--ym-dur-1) ease, color var(--ym-dur-1) ease, transform var(--ym-dur-1) var(--ym-ease-out); }


/* ---------------------------------------------------------------------
   5. MENUS (navbar dropdowns)
   Solid white panels. Shape, spacing and the opening motion live with the
   rest of the menu rules in base.html.
   --------------------------------------------------------------------- */
.dropdown-menu { background-color: var(--ym-card); }
.dropdown-item:active { background-color: rgba(52, 152, 219, 0.14); color: inherit; }
.dropdown-divider { border-top-color: var(--ym-hairline); }


/* ---------------------------------------------------------------------
   6. DIALOGS
   Bootstrap drops a dialog 50px from above. Here it fades in and rises
   8px - and is NOT scaled: scaling a dialog full of text and icons re-draws
   every glyph on every frame, which is what looked like words jittering as
   the dialog appeared. 220ms on a curve without a long tail, so the motion
   is over before the eye starts reading.
   The scrim keeps a SHORT fade on purpose: Bootstrap waits for the scrim to
   finish fading before it even starts showing the dialog, so a longer scrim
   fade would delay every dialog by that much.
   --------------------------------------------------------------------- */
.modal.fade .modal-dialog {
    transform: translateY(8px);
    transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.modal.show .modal-dialog { transform: none; }
.modal.fade { transition: opacity 200ms ease; }
.modal-backdrop.fade { transition: opacity 120ms ease-out; }
.modal-backdrop.show { opacity: 0.45; }
.modal-content { border: 0; box-shadow: var(--ym-shadow-3); }
/* Clicking outside a dialog that must be answered: Bootstrap "bumps" it by
   scaling it up, which makes its text wobble. A 4px lift says the same
   thing without distorting anything. */
.modal.modal-static .modal-dialog { transform: translateY(-4px); transition-duration: var(--ym-dur-1); }


/* ---------------------------------------------------------------------
   7. CONTROLS
   --------------------------------------------------------------------- */

/* Every tappable thing: no 300ms double-tap-to-zoom wait. */
a, button, .btn, label, summary, select, [role="button"], [data-bs-toggle],
input[type="checkbox"], input[type="radio"], input[type="submit"] {
    touch-action: manipulation;
}

/* Buttons react ON PRESS. Transition only what actually changes, so a
   button never animates its size or padding. */
.btn {
    transition: color var(--ym-dur-1) ease, background-color var(--ym-dur-1) ease,
                border-color var(--ym-dur-1) ease, box-shadow var(--ym-dur-1) ease,
                transform var(--ym-dur-2) var(--ym-ease-out);
}
.btn:active:not(:disabled):not(.disabled) {
    transform: scale(0.97);
    transition-duration: var(--ym-dur-press);
}

/* Fields: a soft, wide focus halo in the brand blue (Apple-style) instead of
   a hard outline, and a short colour transition. */
.form-control, .form-select {
    transition: border-color var(--ym-dur-1) ease, box-shadow var(--ym-dur-1) ease, background-color var(--ym-dur-1) ease;
}
.form-control:focus, .form-select:focus {
    border-color: var(--ym-blue);
    box-shadow: var(--ym-focus-ring);
}
.form-check-input { transition: background-color var(--ym-dur-1) ease, border-color var(--ym-dur-1) ease, background-position var(--ym-dur-2) var(--ym-ease-out), box-shadow var(--ym-dur-1) ease; }
.form-check-input:focus { box-shadow: var(--ym-focus-ring); }
.form-check-input:checked { background-color: var(--ym-blue); border-color: var(--ym-blue); }

/* Keyboard focus is always visible - but only for the keyboard. A mouse or
   finger never leaves a ring behind. */
a:focus-visible, [role="button"]:focus-visible, .acc-btn:focus-visible,
.accessibility-fab:focus-visible, summary:focus-visible {
    outline: 3px solid rgba(52, 152, 219, 0.55);
    outline-offset: 2px;
    border-radius: 6px;
}

/* iPhone zooms the whole page into any field whose text is under 16px, and
   leaves it zoomed. The small fields on the site get 16px on touch screens
   only; desktop keeps the original size. (Listed by name - a blanket rule on
   every input would also SHRINK the large ones, such as the reset-code box.) */
@media (pointer: coarse) {
    :root .form-control-sm, :root .form-select-sm {
        font-size: 16px;
    }
}

/* Tab strips: see .ym-segmented in ym-base.css (one shared segmented control). */

/* Progress bars fill on the sheet curve instead of Bootstrap's linear ease. */
.progress-bar { transition: width 0.7s var(--ym-ease-out); }

/* Alerts sit on the page like the rest of the cards. */
.alert { border-width: 0; box-shadow: var(--ym-shadow-1); }

/* Badges: tabular numbers so a counter does not shift its width as it ticks. */
.badge, .notification-badge { font-variant-numeric: tabular-nums; }


/* ---------------------------------------------------------------------
   8. TOUCH SCREENS - no sticky hover
   On a phone or iPad a tap leaves :hover applied until the next tap
   elsewhere, so a card that "lifts on hover" stays lifted after a tap and
   then drops when anything else is touched - a visible jump. On devices with
   no hover, those lifts are cancelled; a short press-down replaces them, so
   touch still gets immediate feedback.
   (`:root` + the page's own selector is what lets this beat the page rule
   that comes later in the document.)
   --------------------------------------------------------------------- */
/* With a mouse: the cards used to jump 5px up whenever the pointer crossed
   them, so moving the mouse across a page set the whole grid bouncing (and
   a card flickered when the pointer sat on its bottom edge - it moved out
   from under the pointer, dropped back, lifted again). 3px on a soft curve
   still answers the pointer but no longer pulls the eye. */
@media (hover: hover) {
    :root :is(.practice-card, .study-card, .nb-card, .article-card,
              .summary-card, .chapter-card):hover {
        transform: translateY(-3px);
    }
}

@media (hover: none) {
    :root :is(.practice-card, .study-card, .nb-card, .article-card, .summary-card,
              .chapter-card, .auth-btn, .logout-btn, .sub-renew-btn, .btn-submit,
              .btn-go-practice, .btn-next-topic, .ym-btn-danger, .btn-demo,
              .social-link, .accessibility-fab, .read-corner-toggle):hover {
        transform: none;
    }
    :root :is(.auth-btn, .logout-btn, .sub-renew-btn, .btn-submit, .btn-go-practice,
              .btn-next-topic, .ym-btn-danger, .btn-demo):active {
        transform: scale(0.97);
        transition-duration: var(--ym-dur-press);
    }
}


/* ---------------------------------------------------------------------
   9. FOOTER
   --------------------------------------------------------------------- */
/* :root for specificity: Bootstrap's own .py-4 is !important too. */
:root footer { padding-bottom: calc(1.5rem + env(safe-area-inset-bottom)) !important; }
.footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    row-gap: 6px;
}
.footer-links a { margin: 0 6px; }
/* On a phone the three links wrap; a separator dot stranded at the start of
   a line looks like a mistake, so the dots go and the gap does the work. */
@media (max-width: 575.98px) {
    .footer-links { column-gap: 14px; }
    .footer-links .footer-sep { display: none; }
}


/* ---------------------------------------------------------------------
   10. SAFE AREAS (iPhone notch / Dynamic Island / home indicator)
   base.html uses viewport-fit=cover so the navy bar and footer run edge to
   edge in landscape. These insets keep the content itself clear of the
   rounded corners and the camera housing.
   --------------------------------------------------------------------- */
.nav-shell {
    padding-left: max(clamp(12px, 1.6vw, 28px), env(safe-area-inset-left)) !important;
    padding-right: max(clamp(12px, 1.6vw, 28px), env(safe-area-inset-right)) !important;
}
footer > .container {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
}


/* ---------------------------------------------------------------------
   11. PAGE-TO-PAGE: NO FLASH
   Moving between pages is a plain, instant navigation. (A cross-fade -
   View Transitions - was tried and removed: during the swap the browser
   briefly showed a bright full-screen frame, a flash that is tiring to look
   at when moving between sections all day.)
   The page canvas itself carries the site background, so anything the
   browser paints before or around the page - between two pages, behind
   iOS's rubber-band overscroll - is the same soft grey, never pure white.
   --------------------------------------------------------------------- */
html { background-color: var(--ym-bg); }


/* ---------------------------------------------------------------------
   12. ACCESSIBILITY PREFERENCES
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .modal.fade .modal-dialog { transform: none; transition: none; }
    .btn:active:not(:disabled):not(.disabled),
    .navbar-toggler:active, .nav-icon-btn:active { transform: none; }
    .navbar-brand:hover i { transform: none; }
    .progress-bar { transition: none; }
}
/* "Increase contrast": a defined edge on the floating surfaces. */
@media (prefers-contrast: more) {
    .dropdown-menu, .accessibility-menu, .modal-content { border: 1px solid var(--ym-ink) !important; }
}
