@import url("tokens.css");

/* Reset some default styles */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-size: 16px;
    font-family: var(--font-sans);
    font-weight: 400;
}

#toast-container>div {
    opacity: 1;
    margin-bottom: 32px;
}

/* Base page colours, from the tokens above - the same cream page and ink
   text as the marketing site. */

body {
    background-color: var(--color-page);
    color: var(--color-text);
    -webkit-font-smoothing: antialiased;
}

/* Zero-specificity so any class (.button, .user-menu-item, ...) that sets
   its own colour still wins, hover included */
:where(a) {
    color: var(--color-primary);
}

:where(a:hover) {
    color: var(--color-primary-dark);
}

/* Other styles */

.body {
    /* 78px navbar (header.css) plus breathing room under its rounded edge */
    margin-top: 86px;
    padding: 20px;
    text-align: center;
}

h1 {
    font-weight: 600;
    margin: 0;
    font-size: 1.75rem;
    line-height: 1.1;
    letter-spacing: -.02em;
}

h2 {
    font-weight: 600;
    margin: 0;
    font-size: 1.5rem;
    letter-spacing: -.015em;
    margin-bottom: 20px;
}

h3 {
    margin: 5px;
    color: lightgrey;
    position: relative;
    width: auto;
    text-align: left;
    font-size: 0.75rem;
}

p {
    font-size: 1rem;
    margin: 16px;
}

#small-font {
    font-size: 0.75rem;
}

/* The app's main panel: a white card on the grey page */
.section {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-card);
    padding: 16px;
    margin-bottom: 20px;
    position: relative;
    text-align: left;
}

.table {
    display: flex;
    justify-content: center;
    align-items: center;
}

.button-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.dropdown-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.chart-container {
    display: flex;
    justify-content: center;
    align-items: center;
    max-width: 600px;
    max-height: 400px;
    margin: 0 auto;
}

/* !important on both: these are "hide this regardless of what else
   targets it" utility classes, used together with plenty of other
   classes that set their own display (.link-button, .button-container,
   .card, ...). Without it, whichever rule simply happens to be declared
   later in the cascade wins on equal specificity - which is exactly how
   #changeSchoolButton (.link-button.display-none) rendered visible on
   page load despite the display-none class, since .link-button's
   display: inline-block came later in this same file. */
.display-none {
    display: none !important;
}

.hidden {
    display: none !important;
}

/* ------------------------------------------------------------------
   Centred single-column layout for the auth and parent-flow pages
   (login, register, reset password, school selection, account,
   profile, and the pickup-request screens). Unlike the staff
   dashboards these pages have no .admin-content wrapper, so their
   .body stretched edge-to-edge on tablet/desktop and read as a
   blown-up phone screen. .body-narrow keeps the content in a
   comfortable centred column at every width; on mobile the max-width
   is wider than the viewport so nothing changes there.
   ------------------------------------------------------------------ */

.body-narrow {
    max-width: 460px;
    margin-left: auto;
    margin-right: auto;
}

/* Opt-in modifier for the short, single-purpose screens at the start of
   the sign-in flow (session_configuration, login) where sitting pinned
   to the top of a tall desktop screen read as sparse. A fixed top offset
   rather than true flexbox centring (which would size to each page's own
   content) is deliberate: session_configuration and login share the same
   "Welcome to School Pickup" heading, and navigating between them - part
   of the same flow - must not visibly shift it, which centring around
   each page's different content height would do. Desktop only - on a
   short mobile viewport the difference isn't worth the extra rule. */
@media (min-width: 600px) {
    .body-centered {
        padding-top: 14vh;
    }
}

/* Buttons/submit inputs fill the column (capped) instead of sitting
   at the old fixed width:20%, which looked stranded on desktop */
.body-narrow .button-container,
.body-narrow form {
    width: 100%;
}

.body-narrow .button,
.body-narrow input[type="submit"],
.body-narrow #submit-button {
    width: 100%;
    max-width: 360px;
}

/* Framed sections and summary tables centre within the column */
.body-narrow .section,
.body-narrow .table {
    max-width: 360px;
    margin-left: auto;
    margin-right: auto;
}

/* Step indicator for the short parent-onboarding sequence (create a
   profile, then enter the school's access code) - without this there was
   no sense of how much further onboarding had left to go. */

.step-indicator {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-bottom: 8px;
}

.step-indicator-segment {
    width: 32px;
    height: 4px;
    border-radius: 2px;
    background-color: var(--color-border-light);
}

.step-indicator-segment.step-indicator-done {
    background-color: var(--color-primary);
}

.step-indicator-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    margin-bottom: 16px;
}

/* A plain button styled to read as a text link - used where an action
   resets/changes something on the current page (so it can't be a real
   <a href>) but should still look like the lightweight links elsewhere
   in the app, not a button. */
.link-button {
    display: inline-block;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font-family: inherit;
    font-size: 0.85rem;
    color: var(--color-primary-dark);
    text-decoration: none;
    cursor: pointer;
}

.link-button:hover {
    text-decoration: underline;
}

/* Placeholder text shown while an AJAX-populated section (favourites,
   search results) hasn't resolved yet, so the section doesn't just look
   empty while it loads */
.inline-loading-text {
    margin: 4px;
    font-size: 0.8rem;
    font-style: italic;
    color: var(--color-text-secondary);
}

/* Scoreboard-style queue position on active_request - a parent checking
   this one-handed, parked or driving up, benefits from a number they can
   read at a glance rather than picking it out of a sentence. The sentence
   itself stays (aria-hidden here) so a screen reader still gets a full
   description instead of a bare digit. */
.queue-position-scoreboard {
    text-align: center;
    margin: 4px 0 2px 0;
}

.queue-position-number {
    display: block;
    font-size: 3.5rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-primary);
}

.queue-position-scoreboard-label {
    display: block;
    margin-top: 4px;
    font-size: 0.75rem;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Small pickup-method icon inline with its label - the same
   drive-through/pedestrian icons already used on class_dashboard's
   cards, reused here (create_request, edit_request) instead of leaving
   the choice as plain text */
.pickup-method-icon-inline {
    height: 18px;
    width: 18px;
    vertical-align: middle;
    margin-right: 6px;
}

/* Queue position progress bar on active_request - a plain, labelled fill
   with a "you are here" marker, replacing a two-colour bar chart whose
   axes and legend were both hidden and so conveyed nothing on its own */
.queue-progress {
    max-width: 360px;
    margin: 10px auto 16px auto;
}

.queue-progress-track {
    position: relative;
    height: 14px;
    border-radius: 7px;
    background-color: var(--color-surface-muted);
    border: 1px solid var(--color-border);
    overflow: visible;
}

.queue-progress-fill {
    height: 100%;
    border-radius: 7px 0 0 7px;
    background-color: var(--color-primary-light);
    transition: width 0.4s ease;
}

.queue-progress-marker {
    position: absolute;
    top: 50%;
    left: 0;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background-color: var(--color-primary);
    border: 3px solid var(--color-surface);
    box-shadow: 0 0 0 1px var(--color-primary);
    transform: translate(-50%, -50%);
    transition: left 0.4s ease;
}

.queue-progress-labels {
    display: flex;
    justify-content: space-between;
    margin-top: 8px;
    font-size: 0.7rem;
    color: var(--color-text-secondary);
}

/* Confetti burst on reaching the front of the queue (see launchConfetti()
   in active_request.html). The app's tagline leans into the "click and
   collect, but for children" framing already, and there was already a
   celebratory emoji here - this leans into that a little further. */
.request-in-progress {
    position: relative;
}

.confetti-container {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.confetti-piece {
    position: absolute;
    top: -10px;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    opacity: 0.9;
    animation-name: confetti-fall;
    animation-timing-function: ease-in;
    animation-fill-mode: forwards;
}

@keyframes confetti-fall {
    0% {
        transform: translateY(0) rotate(0deg);
        opacity: 0.9;
    }
    100% {
        transform: translateY(220px) rotate(360deg);
        opacity: 0;
    }
}

/* Dismissal status pill on active_request - a parent knows what time
   school ends, but not whether staff have actually started letting
   children out yet, so a bare queue number reads as more certain than it
   is. Neutral/grey with a soft pulsing dot while waiting, flips to the
   filled green pill (same tokens as the settings-tab-active badge) once
   /active_request_data reports the first child sent to the gate. */
.dismissal-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 12px 0;
    padding: 5px 12px;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: 500;
    background-color: var(--color-surface-muted);
    color: var(--color-text-secondary);
}

.dismissal-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--color-text-tertiary);
    flex-shrink: 0;
}

.dismissal-status-waiting .dismissal-status-dot {
    animation: dismissal-status-pulse 1.6s ease-in-out infinite;
}

.dismissal-status-started {
    background-color: var(--color-success-bg);
    color: var(--color-success-text);
}

.dismissal-status-started .dismissal-status-dot {
    background-color: var(--color-success-text);
}

@keyframes dismissal-status-pulse {
    0%, 100% {
        opacity: 0.35;
    }
    50% {
        opacity: 1;
    }
}

/* Freshness note under the queue progress bar - replaces a static claim
   that the page "auto-refreshes every 60 seconds" with the actual time of
   the last successful refresh, so a parent can tell a stale-looking number
   apart from a page that has genuinely stopped updating (the symptom
   reported on iOS Safari, where a backgrounded/restored tab could stop
   polling silently). Turns into a warning colour if a poll fails, rather
   than failing silently. */
.last-updated-text {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
}

.last-updated-text-warning {
    color: var(--color-alert);
    font-weight: 500;
}

/* Brief highlight on the scoreboard number when the queue position
   actually changes between polls, so moving up in the queue is something
   a parent notices at a glance rather than something they have to
   re-read the number to catch. */
@keyframes queue-position-flash {
    0% {
        transform: scale(1.18);
        color: var(--color-success-text);
    }
    100% {
        transform: scale(1);
        color: var(--color-primary);
    }
}

.queue-position-number.queue-position-flash {
    animation: queue-position-flash 0.6s ease-out;
}