/* ========== Base Styles ========== */
[hidden] { display: none !important; }

html {
    scrollbar-gutter: stable;
}

body {
    font-family: sans-serif;
    margin: 0;
    padding: 0;
    background: #f5f0e8;
    color: #333;
}

header {
    position: sticky;
    top: 0;
    background: #fdf9f4;
    border-bottom: 1px solid #d0c4b0;
    padding: 0.65rem 1rem;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.site-brand {
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
    color: inherit;
    white-space: nowrap;
    flex-shrink: 0;
}

.site-brand:hover {
    text-decoration: underline;
}

main {
    padding: 1rem;
    max-width: 800px;
    margin: auto;
}

/* Drag handle in the bottom-right corner. `both` rather than `vertical` so the
   grip pulls sideways too; max-width keeps a wide drag from breaking out of the
   form grid, and min-height stops it being collapsed to nothing. */
textarea {
    resize: both;
    min-height: 4.5rem;
    max-width: 100%;
}

/* ========== Header Actions ========== */
.header-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: auto;
}

/* ========== Nav Menu (Burger) ========== */
#nav-menu {
    position: relative;
}

#nav-btn {
    background: none;
    border: 1.5px solid #ccc;
    cursor: pointer;
    color: #444;
    padding: 0.35rem 0.55rem;
    border-radius: 6px;
    font-size: 1.1rem;
    line-height: 1;
    display: flex;
    align-items: center;
    transition: border-color 0.2s, background 0.2s;
}

#nav-btn:hover {
    border-color: #999;
    background: #f5f5f5;
}

.dropdown {
    position: absolute;
    right: 0;
    top: calc(100% + 0.5rem);
    background: #fdf9f4;
    border: 1px solid #d0c4b0;
    border-radius: 10px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.12);
    z-index: 50;
    overflow: hidden;
}

.dropdown a {
    display: block;
    padding: 0.7rem 1rem;
    text-decoration: none;
    color: #333;
    font-size: 0.9rem;
    transition: background 0.15s;
}

.dropdown a:hover {
    background: #d8cebf;
}

.dropdown a + a {
    border-top: 1px solid #d0c4b0;
}

#nav-dropdown {
    min-width: 150px;
}

#nav-dropdown a[aria-current="page"] {
    font-weight: 600;
    background: #e4d9c8;
}

/* ========== Home Page ========== */
.home-main {
    max-width: 1000px;
    margin: 0 auto;
    padding: 4rem 2rem 2rem;
    text-align: center;
}

.hero {
    margin-bottom: 3rem;
}

.site-title {
    font-family: 'Playfair Display', serif;
    font-size: 2.8rem;
    font-weight: 700;
    margin: 0 0 1.5rem;
    letter-spacing: -0.01em;
}

.hero p {
    font-family: 'Playfair Display', serif;
    font-style: italic;
    font-size: 1.05rem;
    line-height: 1.8;
    color: #5a4a38;
    margin: 0 0 1.5rem;
}

.hero hr {
    border: none;
    border-top: 1px solid #c8b89a;
    max-width: 180px;
    margin: 1.5rem auto;
}

.btn-list {
    display: inline-block;
    padding: 0.55rem 1.2rem;
    background: transparent;
    color: #5a3e28;
    text-decoration: none;
    border: 1.5px solid #5a3e28;
    border-radius: 4px;
    font-size: 0.95rem;
    letter-spacing: 0.04em;
    transition: background 0.2s, color 0.2s;
}

.btn-list:hover {
    background: #5a3e28;
    color: #f5f0e8;
}

/* `.home-main` pads 2rem at the sides but the list page's `main` pads 1rem, so
   half of it is cancelled here — otherwise this card is 32px narrower than a
   list row at every width below 1032px. */
.noodle-of-the-day-section {
    text-align: left;
    padding-top: 2rem;
    margin-inline: -1rem;
}

.noodle-of-the-day-section h2 {
    font-family: 'Playfair Display', serif;
    font-size: 0.85rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    text-align: center;
    color: #8a6a4a;
    margin-bottom: 1.25rem;
}

/* Shown when the catalogue cannot be loaded or the chosen noodle fails to
   render. home.js used to swallow both silently, leaving an empty section. */
.notd-error {
    color: #8a6a4a;
    font-style: italic;
    text-align: center;
    margin: 0;
}

#noodle-of-the-day .card {
    background: #fff8f0;
    border-color: #e0ccb0;
}

/* ========== Confirm Dialog ========== */
.confirm-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 200;
    align-items: center;
    justify-content: center;
}

.confirm-backdrop.visible {
    display: flex;
}

.confirm-box {
    background: #f5f0e8;
    border-radius: 12px;
    padding: 1.5rem;
    max-width: 340px;
    width: calc(100% - 2rem);
    box-shadow: 0 8px 32px rgba(0,0,0,0.2);
}

.confirm-box p {
    margin: 0 0 1.25rem;
    font-size: 1rem;
    text-align: center;
}

.confirm-buttons {
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
}

.confirm-buttons button {
    padding: 0.5rem 1.1rem;
    border: 1px solid #ccc;
    border-radius: 6px;
    font-size: 0.95rem;
    cursor: pointer;
    background: #f0f0f0;
}

.confirm-buttons .confirm-ok {
    background: #333;
    color: #fff;
    border-color: #333;
}

/* ========== Overlay ========== */
#overlay {
    display: none;
    position: fixed;
    inset: 0;
    /* dvh tracks the browser's address bar as it shows and hides. Without it
       the overlay is sized to the viewport with the bar retracted, so on a
       browser that keeps its bar on screen (Brave, notably) the bottom of the
       overlay sits behind it. The vh line is the fallback. */
    height: 100vh;
    height: 100dvh;
    background: rgba(0, 0, 0, 0.55);
    z-index: 100;
    /* Deliberately not align-items/justify-content: centring an over-tall card
       splits the overflow evenly above and below, putting the close button off
       the top of the screen — under the address bar — with no way to scroll up
       to it. Auto margins on the card centre it identically when it fits and
       collapse to zero when it does not, so it starts at the top instead. */
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 1rem;
    box-sizing: border-box;
}

#overlay.visible {
    display: flex;
}

#overlay-card {
    background: #f5f0e8;
    border-radius: 14px;
    padding: 1.5rem;
    max-width: 480px;
    width: 100%;
    /* There is no global border-box rule, so without this the 1.5rem padding
       is added outside width/max-height and the card overflows the cap by
       exactly its own padding. */
    box-sizing: border-box;
    margin: auto;
    position: relative;
    box-shadow: 0 8px 32px rgba(0,0,0,0.2);
    /* Column so the body can be the only part that scrolls, keeping the title
       and the close button pinned. 100% is the overlay's content box, which
       already excludes its padding. */
    display: flex;
    flex-direction: column;
    max-height: 100%;
}

/* The scrolling part. min-height:0 because a flex item refuses to shrink below
   its content otherwise, which would push the card past the cap again. */
#overlay-body {
    overflow-y: auto;
    overscroll-behavior: contain;
    min-height: 0;
}

.overlay-toolbar,
#overlay-card h2,
#rating-widget {
    flex-shrink: 0;
}

/* The two controls, pushed into their own corners. Negative margins pull them
   out of the card's 1.5rem padding so they sit near the edges where the eye
   looks for them, rather than floating a full pad inside it. */
.overlay-toolbar {
    display: flex;
    justify-content: space-between;
    /* Enough negative margin to put the glyphs themselves in the corners, not
       just their 44px boxes. The box is mostly padding around a small mark, so
       pulling it only out of the card's padding still left the dots sitting
       inboard of the text below them, which read as a misalignment. */
    margin: -1.25rem -1.25rem 0;
    /* The menu below is anchored to this row. */
    position: relative;
}

/* Its own line, under the buttons: level with them it read as pinned between
   two icons, and this way the full width of the card is available to a long
   name — no padding to tune around the corners. */
#overlay-card h2 {
    margin: 0.25rem 0 1rem;
    font-size: 1.3rem;
    text-align: center;
    overflow-wrap: anywhere;
}

/* 44px square, and round: the hit area is the point, not the glyph. Both sit
   at the edge of a card that fills a phone screen. */
.overlay-icon-button {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: none;
    color: #8d8378;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The dots are drawn, so they take their colour from the button. */
.overlay-icon-button svg circle {
    fill: currentColor;
}

/* Colour only, no shading — the buttons are marks in the corners of the card,
   not chips sitting on it. */
.overlay-icon-button:hover {
    color: #3a3226;
}

.overlay-icon-button:focus-visible {
    outline: 2px solid #8a6a4a;
    outline-offset: -2px;
}

/* Hangs from the left edge of the toolbar, under the ⋮ that opens it. Anchored
   right it opened across the card towards the close button. */
.overlay-menu {
    position: absolute;
    top: calc(100% + 0.25rem);
    left: 0;
    z-index: 1;
    min-width: 11rem;
    padding: 0.25rem;
    background: #fdf9f4;
    border: 1px solid #c8b89a;
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
    display: flex;
    flex-direction: column;
}

.overlay-menu button {
    background: none;
    border: none;
    border-radius: 6px;
    font: inherit;
    font-size: 0.95rem;
    text-align: left;
    color: #3a3226;
    padding: 0.75rem;
    cursor: pointer;
}

/* The one item in here that destroys something. Set apart so a thumb reaching
   for Edit does not find it by accident. */
.menu-danger {
    color: #a4432e;
    margin-top: 0.25rem;
    border-top: 1px solid #ece4d5;
    border-radius: 0 0 6px 6px;
}

.overlay-menu button:hover {
    background: #f1e9dc;
}

.overlay-menu button:focus-visible {
    outline: 2px solid #8a6a4a;
    outline-offset: -2px;
}

/* Matches the geometry of `main` on the list page (800px content box) so the
   card here is exactly as wide as a list row rather than a narrower variant —
   the narrow version could not fit the one-line mobile stats row and pushed
   the price outside the border. */
#noodle-of-the-day {
    margin: 0 auto;
    max-width: 800px;
    /* Same grid as #noodle-list. As a plain block the card could not grow past
       its container, so a stats row too wide to fit spilled the price outside
       the border instead of widening the card the way a list row does. */
    display: grid;
    grid-template-columns: 1fr;
}

/* ========== Form Styles ========== */
form {
    display: grid;
    gap: 1rem;
}

form input,
form textarea,
form select,
form button {
    padding: 0.5rem;
    font-size: 1rem;
    width: 100%;
    box-sizing: border-box;
    background: #fdf9f4;
    border: 1px solid #c8b89a;
    border-radius: 4px;
}

form#add-form>div:not(.barcode-row):not(#reader-container):not(.rating-row):not(.spice-row):not(.checkbox-row) {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 10px;
    padding: 10px;
    max-width: 100%;
}

@media (max-width: 768px) {
    form#add-form>div {
        grid-template-columns: 1fr;
    }

    button[type="submit"] {
        justify-self: center;
    }
}

/* ========== My List ========== */
.my-score-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.35rem;
    padding-top: 0.35rem;
    border-top: 1px dashed #e0d6c4;
}

.my-score-label {
    color: #888;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.my-score-row .stars {
    font-size: 0.95rem;
}

.my-score-row .spice {
    font-size: 0.75rem;
}

/* ========== Sign In ========== */
.signin-choices {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 320px;
}

.signin-btn {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.75rem 1rem;
    border: 1px solid #d0c4b0;
    border-radius: 8px;
    background: #fdf9f4;
    color: #333;
    text-decoration: none;
    font-size: 0.95rem;
    transition: background 0.15s, border-color 0.15s;
}

.signin-btn:hover {
    background: #f0e7d8;
    border-color: #b9a888;
}

.signin-links {
    display: flex;
    gap: 1rem;
}

/* ========== Review Queue ========== */
.queue-card {
    border: 1px solid #d0c4b0;
    background: #faf6f0;
    border-radius: 10px;
    padding: 1rem;
    margin-bottom: 1.25rem;
    gap: 0.6rem;
}

.queue-card-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid #e0d6c4;
}

.queue-card-head strong {
    font-size: 1.05rem;
}

.queue-thumb {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 6px;
    flex-shrink: 0;
}

/* Pushed to its own line so a long submitter id cannot squeeze the name. */
.queue-meta {
    color: #8a6a4a;
    font-size: 0.75rem;
    margin-left: auto;
    text-align: right;
}

/* Tells the two kinds of queue card apart at a glance, before reading either. */
.queue-badge {
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #fff;
    background: #8a6a4a;
    border-radius: 999px;
    padding: 0.15rem 0.5rem;
    flex-shrink: 0;
}

.queue-card-edit {
    border-left: 3px solid #8a6a4a;
}

.queue-gone {
    font-size: 0.85rem;
    color: #a33;
    margin: 0.75rem 0 0;
}

.queue-field {
    display: grid;
    gap: 0.2rem;
}

/* Only fields the submitter actually changed get the marker and the `now:`
   line, so the owner can review the diff rather than re-read the whole card. */
.queue-field-changed {
    border-left: 3px solid #c9a227;
    padding-left: 0.6rem;
    margin-left: -0.6rem;
}

.queue-was {
    font-size: 0.7rem;
    color: #8a6a4a;
    font-style: italic;
}

/* Names the noodle being edited on the suggest-edit form, which has no
   barcode field to identify it. */
.edit-target {
    font-weight: 600;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid #e0d6c4;
}

.queue-field span {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #8a6a4a;
}


.queue-actions {
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
    padding-top: 0.25rem;
}

/* `form button` is width:100% for the single-button forms elsewhere; these two
   sit side by side. */
.queue-actions button {
    width: auto;
    padding: 0.5rem 1.4rem;
    cursor: pointer;
}

.queue-actions button:disabled {
    opacity: 0.5;
    cursor: default;
}

.queue-approve {
    background: #5a3e28;
    color: #f5f0e8;
    border-color: #5a3e28;
}

.queue-reject {
    background: transparent;
    color: #8a3a2a;
    border-color: #d3b5ac;
}

@media (max-width: 600px) {
    .queue-card-head {
        flex-wrap: wrap;
    }

    .queue-meta {
        margin-left: 0;
        text-align: left;
        flex-basis: 100%;
    }
}

/* ========== Page Intro ========== */
.page-heading {
    margin: 1.25rem 0 0.25rem;
}

.page-intro {
    margin: 0 0 1.25rem;
    color: #666;
    font-size: 0.9rem;
    line-height: 1.45;
}

/* ========== Star Rating & Spice Level (form) ========== */
.rating-row,
.spice-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.rating-stars,
.spice-chilies {
    display: flex;
    flex-direction: row-reverse;
    gap: 5px;
}

/* "None" sits outside .spice-chilies so the checked~label fill trick still
   works for 1-5, while 0 highlights nothing. */
.spice-picker {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.spice-none-input {
    display: none;
}

.spice-none {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #999;
    border: 1px solid #d0c4b0;
    border-radius: 999px;
    padding: 0.15rem 0.6rem;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
}

.spice-none-input:checked + .spice-none {
    background: #444;
    border-color: #444;
    color: #fff;
}

.rating-stars input,
.spice-chilies input {
    display: none;
}

.rating-stars label {
    font-size: 2em;
    color: #ccc;
    cursor: pointer;
    transition: color 0.2s;
}

.rating-stars input:checked~label,
.rating-stars label:hover,
.rating-stars label:hover~label {
    color: gold;
}

.spice-chilies label {
    font-size: 1.25em;
    line-height: 1;
    display: flex;
    align-items: center;
    opacity: 0.2;
    filter: grayscale(100%);
    cursor: pointer;
    transition: opacity 0.2s, filter 0.2s;
}

.spice-chilies input:checked~label,
.spice-chilies label:hover,
.spice-chilies label:hover~label {
    opacity: 1;
    filter: none;
}

/* ========== List Filters ========== */
.list-filters {
    margin-top: 1rem;
    display: flex;
    gap: 0.5rem;
}

.list-filters input[type="text"],
.list-filters select {
    padding: 0.5rem;
    font-size: 1rem;
    border: 1px solid #c8b89a;
    border-radius: 6px;
    background: #fdf9f4;
    box-sizing: border-box;
}

.list-filters input[type="text"] {
    flex: 1;
    min-width: 0;
}

.list-filters select {
    cursor: pointer;
}

/* Sits as the last child of the card grid, so it spans the column and reads as
   the end of the (capped) list rather than as a card. */
.show-all {
    padding: 0.6rem;
    font-size: 0.95rem;
    color: #8a6a4a;
    background: #fdf9f4;
    border: 1px dashed #c8b89a;
    border-radius: 6px;
    cursor: pointer;
}

.show-all:hover {
    background: #f1e9dc;
}

/* Stands in for the score meters on a noodle nobody has rated. Quiet rather
   than alarming: it is an invitation, not a missing value. */
.unrated {
    color: #8d8378;
    font-size: 0.85rem;
    font-style: italic;
}

/* Sits where the cards would be: a failed load, an empty index, or a search
   that matched nothing. */
.list-empty {
    margin: 0;
    padding: 1.5rem 0;
    color: #6a6055;
    text-align: center;
}

/* ========== Noodle Cards ========== */
#noodle-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    margin-top: 1rem;
}

.card {
    border: 1px solid #d0c4b0;
    background: #faf6f0;
    padding: 1rem;
    border-radius: 10px;
    display: flex;
    align-items: stretch;
    gap: 1rem;
    cursor: pointer;
    transition: box-shadow 0.15s;
}

.card:hover {
    box-shadow: 0 4px 14px rgba(0,0,0,0.1);
}

.card img {
    width: 72px;
    height: 72px;
    object-fit: cover;
    border-radius: 6px;
    flex-shrink: 0;
}

.card-content {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1;
    justify-content: space-between;
}

.card-title {
    text-align: center;
}

.card-title .brand::before {
    content: "(";
}

.card-title .brand::after {
    content: ")";
}


.price {
    font-weight: bold;
    color: #444;
}

.stars {
    color: gold;
    font-size: 1.1rem;
}

.spice {
    font-size: 0.95rem;
    line-height: 1.2;
}

/* Fractional score meter: a full row of glyphs with a clipped, coloured copy
   layered on top, so 3.7 renders as 74% of the row. */
.rating-meter {
    position: relative;
    display: inline-block;
    white-space: nowrap;
    vertical-align: middle;
}

.rating-meter-fill {
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    white-space: nowrap;
    pointer-events: none;
}

.stars .rating-meter-track {
    color: #d5d5d5;
}

.stars .rating-meter-fill {
    color: gold;
}

.spice .rating-meter-track {
    opacity: 0.3;
    filter: grayscale(100%);
}

.rating-count {
    color: #888;
    font-size: 0.75rem;
    vertical-align: middle;
}

/* Exact score tooltip. Native `title` never fires on touch, so this reveals on
   hover for a mouse and on tap for everyone. */
.has-tip {
    position: relative;
    cursor: help;
}

.has-tip::after {
    content: attr(data-tip);
    position: absolute;
    bottom: 100%;
    left: 0;
    margin-bottom: 0.3rem;
    padding: 0.3rem 0.5rem;
    border-radius: 4px;
    background: #333;
    color: #fff;
    font-size: 0.75rem;
    line-height: 1.3;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.12s;
    z-index: 5;
}

.card-stats .spice.has-tip::after,
.rating-spice-row .spice.has-tip::after {
    left: auto;
    right: 0;
}

@media (hover: hover) {
    .has-tip:hover::after {
        opacity: 1;
        visibility: visible;
    }
}

.has-tip.tip-open::after,
.has-tip:focus-visible::after {
    opacity: 1;
    visibility: visible;
}

.card-stats {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    width: 100%;
}

.card-stats .price {
    text-align: center;
}

.card-stats .spice {
    text-align: right;
}

.rating-spice-row {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}

.rating-spice-row .stars {
    flex-grow: 1;
    text-align: left;
}

.rating-spice-row .spice {
    text-align: right;
}

.community-summary {
    color: #666;
    font-size: 0.85rem;
    margin: 0.25rem 0 0.5rem;
}

/* ========== Overlay Rating Widget ========== */
#rating-widget {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid #e0d6c4;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.rating-widget-heading {
    font-weight: bold;
    color: #444;
}

#rating-widget .rating-stars label {
    font-size: 1.5em;
}

.rating-widget-footer {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.25rem;
}

/* `form button` is full-width for the add form; the widget's button is not. */
#rating-submit {
    width: auto;
    padding: 0.4rem 1rem;
}

#rating-submit:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Quiet, and pushed to the far end of the row: it undoes work rather than
   doing any, so it should never compete with Save for the thumb. `form button`
   is full-width on the add form, hence the width reset. */
#rating-remove {
    margin-left: auto;
    width: auto;
    padding: 0.4rem 0;
    border: none;
    background: none;
    color: #8d8378;
    font-size: 0.8rem;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

#rating-remove:hover {
    color: #a4432e;
}

#rating-remove:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Matches .menu-danger: the confirm dialog's action button carries the same
   weight as the control that opened it. */
.confirm-buttons .confirm-danger {
    background: #a4432e;
    border-color: #a4432e;
    color: #fdf9f4;
}

/* ========== Barcode Scanner ========== */
#reader-container {
    position: relative;
    overflow: hidden;
    border-radius: 8px;
}

#video-preview {
    cursor: crosshair;
}

#video-preview:active {
    filter: brightness(1.15);
}

#reader-container.scanning::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 2px;
    background: rgba(255, 80, 80, 0.85);
    animation: scanline 1.8s ease-in-out infinite;
}

@keyframes scanline {
    0%   { top: 10%; }
    50%  { top: 88%; }
    100% { top: 10%; }
}


.barcode-row {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
}

.barcode-row input[type="text"] {
    flex: 0 1 90%;
    min-width: 0;
}

.barcode-row button {
    flex: 0 1 10%;
}

.checkbox-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.checkbox-row input[type="checkbox"] {
    width: 1.4rem;
    height: 1.4rem;
    margin: 0;
    cursor: pointer;
    flex-shrink: 0;
}


/* ========== Auth Widget ========== */
#auth-widget {
    position: relative;
    flex-shrink: 0;
}

#auth-btn {
    background: none;
    border: 1.5px solid #ccc;
    cursor: pointer;
    color: #444;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    white-space: nowrap;
    transition: border-color 0.2s, background 0.2s, color 0.2s;
}

#auth-btn:hover {
    border-color: #999;
    background: #f5f5f5;
    color: #111;
}

#auth-btn:has(.auth-avatar) {
    border-color: transparent;
    padding: 0.2rem;
}

.auth-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #333;
    color: #fff;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1;
    user-select: none;
}

#auth-menu {
    min-width: 200px;
}

#auth-menu a {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    white-space: nowrap;
}

#auth-menu-user {
    display: flex;
    flex-direction: column;
}

#auth-username {
    padding: 0.6rem 1rem;
    font-size: 0.85rem;
    color: #888;
    border-bottom: 1px solid #eee;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ========== Pagination ========== */
#pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-top: 1.5rem;
    padding-bottom: 1.5rem;
    font-size: 0.95rem;
    color: #555;
}

#pagination button {
    padding: 0.4rem 0.9rem;
    border: 1px solid #c8b89a;
    border-radius: 6px;
    background: #fdf9f4;
    cursor: pointer;
    font-size: 0.9rem;
}

#pagination button:hover:not(:disabled) {
    background: #d8cebf;
}

#pagination button:disabled {
    opacity: 0.35;
    cursor: default;
}

/* ========== Open Food Facts status ========== */
#offf-status {
    color: #888;
    font-size: 0.8rem;
    margin-top: -0.25rem;
}

/* ========== Toast ========== */
#toast {
    position: fixed;
    bottom: 1.5rem;
    left: 50%;
    transform: translateX(-50%);
    padding: 0.65rem 1.25rem;
    border-radius: 8px;
    font-size: 0.95rem;
    box-shadow: 0 4px 16px rgba(0,0,0,0.15);
    z-index: 300;
    white-space: nowrap;
    opacity: 1;
    transition: opacity 0.4s;
}

#toast.toast-success {
    background: #2e7d32;
    color: #fff;
}

#toast.toast-error {
    background: #c62828;
    color: #fff;
}

#toast.toast-fade {
    opacity: 0;
}

#toast button {
    background: none;
    border: none;
    color: inherit;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    margin-left: 0.75rem;
    opacity: 0.8;
    padding: 0;
}

#toast button:hover {
    opacity: 1;
}

/* ========== Profile Page ========== */
.profile-heading {
    font-family: 'Playfair Display', serif;
    font-size: 2rem;
    margin: 1.5rem 0 1.5rem;
}

.stats-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin-bottom: 2rem;
}

.stat-card {
    background: #fdf9f4;
    border: 1px solid #d0c4b0;
    border-radius: 10px;
    padding: 1.25rem 1rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: #3d2b1f;
}

.stat-label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #8a6a4a;
}

.profile-section {
    margin-bottom: 2rem;
}

.profile-section-title {
    font-family: 'Playfair Display', serif;
    font-size: 0.85rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    color: #8a6a4a;
    border-top: 1px solid #c8b89a;
    padding-top: 1rem;
    margin-bottom: 1rem;
}

.dist-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.4rem;
}

.dist-label {
    color: gold;
    font-size: 0.9rem;
    min-width: 5rem;
    text-align: right;
    flex-shrink: 0;
}

.dist-bar-wrap {
    flex: 1;
    background: #e8dfd0;
    border-radius: 4px;
    height: 12px;
    overflow: hidden;
}

.dist-bar {
    height: 100%;
    background: #8a6a4a;
    border-radius: 4px;
    transition: width 0.4s ease;
}

.dist-count {
    font-size: 0.85rem;
    color: #666;
    min-width: 1.5rem;
}

.brand-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 0;
    border-bottom: 1px solid #e8dfd0;
    font-size: 0.95rem;
}

.brand-count {
    color: #8a6a4a;
    font-size: 0.85rem;
}

.highlights-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

.highlight-card {
    background: #fdf9f4;
    border: 1px solid #d0c4b0;
    border-radius: 10px;
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    align-items: center;
    text-align: center;
}

.highlight-card:hover {
    box-shadow: 0 4px 14px rgba(0,0,0,0.1);
}

.highlight-card img {
    max-width: 80px;
    height: auto;
    object-fit: contain;
    margin: 0.5rem 0;
}

.highlight-label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: #8a6a4a;
    font-weight: 700;
}

@media (max-width: 600px) {
    .stats-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .highlights-grid {
        grid-template-columns: 1fr;
    }
}

/* ========== Responsive ========== */
@media (max-width: 600px) {
    .hero p {
        text-align: justify;
    }

    /* Same horizontal padding as `main`, so the card gets the same width it
       would on the list page — which leaves nothing to cancel out. */
    .home-main {
        padding: 2rem 1rem 1rem;
    }

    .noodle-of-the-day-section {
        margin-inline: 0;
    }

    .site-title {
        font-size: 1.9rem;
    }

    /* Compact list row: thumbnail left, name/brand and scores stacked beside
       it. Stacking these vertically wastes most of a phone's width. */
    .card {
        align-items: center;
        gap: 0.75rem;
        padding: 0.75rem;
    }

    .card img {
        width: 64px;
        height: 64px;
    }

    .card-content {
        gap: 0.2rem;
        justify-content: center;
        /* Without this a long name refuses to shrink and pushes the row wide. */
        min-width: 0;
    }

    .card-title {
        text-align: left;
        line-height: 1.25;
    }

    .card-title .brand {
        display: block;
        font-size: 0.8rem;
    }

    /* On its own line the parentheses just add noise. */
    .card-title .brand::before,
    .card-title .brand::after {
        content: none;
    }

    /* One line: score, heat, price hard right. */
    .card-stats {
        display: flex;
        align-items: center;
        justify-content: flex-start;
        flex-wrap: nowrap;
        gap: 0.5rem;
    }

    /* Keep the meter and its count on one line — without this the count wraps
       below the stars on narrow phones and the row becomes three lines. */
    .card-stats .stars {
        font-size: 1rem;
        white-space: nowrap;
        flex-shrink: 0;
    }

    .card-stats .rating-count {
        font-size: 0.7rem;
    }

    /* Reordered so both meters sit together on the left and the price is
       pinned right, rather than the price landing mid-row. */
    .card-stats .spice {
        order: 2;
        font-size: 0.8rem;
        text-align: left;
    }

    .card-stats .price {
        order: 3;
        margin-left: auto;
        text-align: right;
        white-space: nowrap;
    }
}

/* Very narrow phones: the meters plus price no longer fit one line, so drop
   the rating count — it is still on the tooltip and in the overlay. */
@media (max-width: 359px) {
    .card-stats .rating-count {
        display: none;
    }

    .card-stats .stars {
        font-size: 0.9rem;
    }

    .card-stats .spice {
        font-size: 0.7rem;
    }
}
