/* ==========================================================================
   Shared site shell: design tokens, wallpaper, top navigation, buttons.
   Loaded on every page; page-specific sheets load after and may override.
   ========================================================================== */

:root {
    /* Pulled from the shop logo: olive script green, mid pistachio, and the
       brown of the MOCHI wordmark. */
    --primary-color: #6f7d43;
    --secondary-color: #8b9a58;
    --brand-brown: #836c4d;
    --brand-cream: #fdf9ee;
    --success-color: #10b981;
    --danger-color: #ef4444;
    --warning-color: #f59e0b;
    --gray-50: #f9fafb;
    --gray-100: #f3f4f6;
    --gray-200: #e5e7eb;
    --gray-300: #d1d5db;
    --gray-500: #6b7280;
    --gray-700: #374151;
    --gray-900: #111827;
    --border-radius: 8px;
    --box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
    --box-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
    --transition: all 0.2s ease;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
                 'Helvetica Neue', Arial, sans-serif;
    color: var(--gray-900);
    background-color: var(--brand-cream);
    background-image: url('../img/dog-wallpaper.svg');
    background-repeat: repeat;
    background-size: 220px 220px;
    background-attachment: fixed;
    min-height: 100vh;
}

/* Top navigation */
.site-nav {
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 14px 28px;
    background: rgba(255, 255, 255, 0.95);
    border-bottom: 1px solid var(--gray-200);
    box-shadow: var(--box-shadow);
    position: sticky;
    top: 0;
    z-index: 50;
    flex-wrap: wrap;
}

.site-brand {
    font-size: 1.15em;
    font-weight: 700;
    color: var(--gray-900);
    text-decoration: none;
    white-space: nowrap;
}

.site-links {
    display: flex;
    gap: 6px;
    flex: 1;
    /* Without an explicit min-width, a flex item does not shrink below
       its own content's width no matter what overflow says - that's what
       let this row's real (wide) content silently push past its allotted
       box and butt straight up against the bell/name/buttons with no gap,
       even though overflow-x:auto below looks like it should have
       clipped it. min-width:0 is what actually lets the box stop at the
       space .site-nav gave it. */
    min-width: 0;
    /* flex-shrink:0 on the links themselves (below) stops their own text
       from clipping, but that only pushes the overflow problem up a
       level - without this, once there are enough tabs the whole row no
       longer fits and .site-nav's own flex-wrap wraps this entire block
       onto a second line, landing under the notification bell instead of
       above it. Scrolling this row horizontally keeps every tab at full
       size without needing the rest of the header to reflow. */
    overflow-x: auto;
    flex-wrap: nowrap;
    scrollbar-width: none;
    /* A hint that there's more to scroll to, since the hidden scrollbar
       otherwise gives no visual cue at all. */
    mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
}

.site-links::-webkit-scrollbar {
    display: none;
}

.site-links a {
    padding: 7px 14px;
    border-radius: 6px;
    color: var(--gray-700);
    text-decoration: none;
    font-weight: 500;
    font-size: 0.95em;
    transition: var(--transition);
    /* Without this, the flex row shrinks its items (including the
       "Consult the Stylist" pill) below their own content's width once
       there are enough tabs to run out of room - overflow:hidden on the
       pill then clips its own label's right side instead of the row
       simply wrapping or scrolling. */
    flex-shrink: 0;
}

.site-links a:hover {
    background: var(--gray-100);
    color: var(--gray-900);
}

.site-links a.active {
    /* A light tint, not a solid fill of --primary-color (#6f7d43) - that's
       the exact same color the "Consult the Stylist" gradient button
       starts from, so a normal tab and that one looked equally "selected"
       side by side. */
    background: color-mix(in srgb, var(--primary-color) 20%, white);
    color: var(--primary-color);
}

.site-note {
    font-size: 0.8em;
    color: var(--gray-500);
    padding: 4px 10px;
    border: 1px dashed var(--gray-300);
    border-radius: 999px;
    white-space: nowrap;
}

/* Page shell */
.page {
    max-width: 1200px;
    margin: 0 auto;
    padding: 28px 20px 60px;
}

.page-header {
    margin-bottom: 22px;
}

.page-header h1 {
    font-size: 1.9em;
    font-weight: 700;
    margin-bottom: 6px;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
}

.page-header p {
    color: var(--gray-700);
}

.panel {
    background: white;
    border: 1px solid rgba(255, 255, 255, 0.9);
    border-radius: var(--border-radius);
    padding: 24px;
    box-shadow: 0 4px 6px -1px rgba(17, 24, 39, 0.1),
                0 10px 20px -5px rgba(17, 24, 39, 0.12);
}

/* Buttons */
.btn {
    padding: 10px 18px;
    border: none;
    border-radius: 6px;
    font-size: 0.95em;
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition);
    font-family: inherit;
}

/* A <label class="btn"> (an upload button wrapping a hidden file input)
   or an <a class="btn"> (a link styled as a button, e.g. "My profile")
   is an inline element by default - its vertical padding paints outside
   its own line box and visually overlaps whatever text sits right above
   or below it, rather than reserving real space the way a <button>'s
   own inline-block default already does. */
label.btn,
a.btn {
    display: inline-block;
}

.btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.btn-primary {
    background: var(--primary-color);
    color: white;
}

.btn-primary:hover:not(:disabled) {
    background: var(--secondary-color);
}

.btn-secondary {
    background: var(--gray-200);
    color: var(--gray-700);
}

.btn-secondary:hover:not(:disabled) {
    background: var(--gray-300);
}

.btn-danger {
    background: var(--danger-color);
    color: white;
}

.btn-ghost {
    background: white;
    color: var(--gray-700);
    border: 1px solid var(--gray-300);
    padding: 8px 14px;
}

.btn-ghost:hover:not(:disabled) {
    border-color: var(--primary-color);
    color: var(--primary-color);
}

/* Toast (shared with the frame tool) */
.toast {
    position: fixed;
    bottom: 24px;
    right: 24px;
    max-width: 420px;
    padding: 14px 20px;
    border-radius: var(--border-radius);
    background: var(--gray-900);
    color: white;
    box-shadow: var(--box-shadow-lg);
    z-index: 2000;
    font-weight: 500;
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.toast.hidden {
    opacity: 0;
    transform: translateY(12px);
    pointer-events: none;
}

.toast.success { background: var(--success-color); }
.toast.error   { background: var(--danger-color); }
.toast.warning { background: var(--warning-color); }

@media (max-width: 700px) {
    .site-nav {
        gap: 12px;
        padding: 12px 16px;
    }

    /* Same horizontal-scroll approach as the base rule, not a second
       flex-wrap:wrap override - wrapping here made .site-links grow
       taller than one line while still being a single flex item in
       .site-nav's own row, so the notification bell (vertically centered
       against that taller item) ended up sitting on top of whichever
       link wrapped onto the second internal row instead of the row
       simply scrolling sideways. */
    .site-links {
        gap: 4px;
    }

    .site-links a {
        padding: 6px 10px;
        font-size: 0.9em;
    }

    .site-note {
        display: none;
    }
}

/* ==========================================================================
   Brand: logo lockup and Instagram link
   ========================================================================== */

.site-brand {
    display: flex;
    align-items: center;
    gap: 10px;
}

.site-logo {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    display: block;
    /* The logo art sits on cream, so a matching ring hides the seam against
       the white nav bar. */
    background: var(--brand-cream);
    box-shadow: 0 0 0 1px rgba(111, 125, 67, 0.25);
}

.site-brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
}

.site-brand-text strong {
    font-size: 1.02em;
    font-weight: 700;
    color: var(--primary-color);
    letter-spacing: 0.01em;
}

.site-brand-text em {
    font-style: normal;
    font-size: 0.7em;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--brand-brown);
}

.site-instagram {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border: 1px solid var(--gray-300);
    border-radius: 999px;
    color: var(--brand-brown);
    text-decoration: none;
    font-size: 0.78em;
    font-weight: 600;
    white-space: nowrap;
    transition: var(--transition);
}

.site-instagram:hover {
    border-color: var(--primary-color);
    color: var(--primary-color);
    background: var(--brand-cream);
}

@media (max-width: 900px) {
    .site-instagram span {
        display: none;
    }
}

/* ==========================================================================
   Nav session chrome
   Lives here, not in login.css: the nav is rendered by base.html on every
   page, so page-scoped styles left it unstyled everywhere except /login
   and /team.
   ========================================================================== */

.site-user {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.86em;
    font-weight: 600;
    color: var(--gray-700);
    white-space: nowrap;
    text-decoration: none;
}

.site-user:hover {
    color: var(--primary-color);
}

.role-badge {
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 0.78em;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background: var(--gray-200);
    color: var(--gray-700);
}

.role-badge.admin  { background: var(--primary-color); color: white; }
.role-badge.groomer { background: #ddd6fe; color: #5b21b6; }
.role-badge.parent { background: #d1fae5; color: #047857; }

.site-signout {
    font-size: 0.86em;
    font-weight: 600;
    color: var(--gray-500);
    text-decoration: none;
    padding: 6px 12px;
    border: 1px solid var(--gray-300);
    border-radius: 6px;
    white-space: nowrap;
}

.site-signout:hover {
    color: var(--gray-900);
    border-color: var(--gray-500);
}

/* --------------------------------------------------------------------------
   Notification center — a bell in the nav, its panel dropping down from the
   header's bottom-right corner.
   -------------------------------------------------------------------------- */

.notif-center {
    position: relative;
}

.notif-bell {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 1px solid var(--gray-200);
    background: white;
    color: var(--gray-600);
    cursor: pointer;
    transition: var(--transition);
}

.notif-bell:hover {
    background: var(--gray-100);
    color: var(--gray-900);
}

.notif-badge {
    position: absolute;
    top: -3px;
    right: -3px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: #c0392b;
    color: white;
    font-size: 0.66em;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
}

.notif-badge.hidden {
    display: none;
}

.notif-panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: 300px;
    max-height: 380px;
    overflow-y: auto;
    background: white;
    border: 1px solid var(--gray-200);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(76, 66, 42, 0.18);
    z-index: 60;
    padding: 10px;
}

.notif-panel.hidden {
    display: none;
}

.notif-panel-title {
    font-size: 0.82em;
    font-weight: 700;
    color: var(--gray-700);
    padding: 4px 6px 8px;
    border-bottom: 1px solid var(--gray-200);
    margin-bottom: 6px;
}

.notif-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.notif-empty {
    padding: 16px 6px;
    text-align: center;
    font-size: 0.84em;
    color: var(--gray-400);
}

.notif-item {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 7px;
    border-radius: 8px;
    text-decoration: none;
    color: inherit;
    transition: var(--transition);
}

.notif-item:hover {
    background: var(--gray-100);
}

.notif-item-cover {
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--gray-100);
}

.notif-item-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.notif-item-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.notif-item-title {
    font-size: 0.85em;
    font-weight: 600;
    color: var(--gray-900);
}

.notif-item-snippet {
    font-size: 0.78em;
    color: var(--gray-500);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 640px) {
    .notif-panel {
        width: 260px;
        right: -40px;
    }
}


/* ==========================================================================
   Modal component

   Lives here, not in booking.css: the same modal markup is now used by the
   calendar, a client's page and the Appointments tab. While these rules were
   page-scoped, `.modal.hidden` had no `display: none` anywhere except the
   calendar — so closing a modal on any other page did nothing at all.
   ========================================================================== */

.modal {
    position: fixed;
    inset: 0;
    background: rgba(17, 24, 39, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 20px;
}

.modal.hidden {
    display: none;
}

.modal-card {
    background: white;
    border-radius: var(--border-radius);
    padding: 28px;
    width: 100%;
    max-width: 620px;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: var(--box-shadow-lg);
    position: relative;
}

.modal-card.narrow {
    max-width: 420px;
}

.modal-card h2 {
    font-size: 1.3em;
    margin-bottom: 6px;
}

/* An unmistakable close control, top-right of every modal: a bordered
   circle rather than a bare glyph, turning red on hover so it reads as
   "dismiss" at a glance. */
.modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--gray-300);
    border-radius: 50%;
    background: white;
    font-size: 22px;
    line-height: 1;
    color: var(--danger-color);
    cursor: pointer;
    transition: var(--transition);
    z-index: 3;
}

.modal-close:hover {
    background: var(--danger-color);
    border-color: var(--danger-color);
    color: white;
    transform: scale(1.06);
}

.modal-close:focus-visible {
    outline: 2px solid var(--danger-color);
    outline-offset: 2px;
}

.modal-meta {
    color: var(--gray-500);
    font-size: 0.9em;
    margin-bottom: 18px;
}

.edit-booking-consultations {
    margin-bottom: 18px;
    padding: 12px 14px;
    border-radius: 8px;
    background: var(--gray-50, #f8f6f0);
    border: 1px solid var(--gray-200, #e6e2d8);
}

.edit-booking-consultations h3 {
    margin: 0 0 10px;
    font-size: 0.95em;
}

.consultation-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.consultation-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.consultation-row img {
    width: 40px;
    height: 40px;
    border-radius: 6px;
    object-fit: cover;
    flex: none;
}

.consultation-meta {
    flex: 1;
    min-width: 0;
    font-size: 0.85em;
    color: var(--gray-700);
    text-decoration: none;
}

.consultation-meta:hover {
    text-decoration: underline;
}

.consultation-link-btn {
    flex: none;
    font-size: 0.82em;
    padding: 6px 10px;
}


/* ==========================================================================
   Pet record component

   Shared by the calendar's side panel, a client's page and anywhere else a
   dog's details are shown — so it belongs here rather than in booking.css.
   While these lived in the page-scoped sheet, the client page rendered the
   facts list with browser defaults and looked like a jumble.
   ========================================================================== */

/* Two columns: field name, then value. Rows are separated by a hairline so a
   long value stays readable against its own label. */
.pet-facts {
    display: grid;
    grid-template-columns: minmax(84px, max-content) minmax(0, 1fr);
    align-items: baseline;
    column-gap: 16px;
    font-size: 0.86em;
    margin: 0;
}

.pet-facts dt,
.pet-facts dd {
    padding: 7px 0;
    border-top: 1px solid var(--gray-200);
}

.pet-facts > dt:first-of-type,
.pet-facts > dt:first-of-type + dd {
    border-top: none;
}

.pet-facts dt {
    color: var(--gray-500);
    font-weight: 600;
    white-space: nowrap;
}

.pet-facts dd {
    color: var(--gray-900);
    margin: 0;
    /* Long coat descriptions wrap instead of stretching the column */
    overflow-wrap: anywhere;
}

.pet-alerts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.pet-alerts:empty {
    display: none;
}

.pet-alert {
    padding: 3px 10px;
    border-radius: 999px;
    background: #fffbeb;
    border: 1px solid #fde68a;
    color: #92400e;
    font-size: 0.76em;
    font-weight: 600;
}

.pet-section {
    margin-top: 16px;
    padding-top: 13px;
    border-top: 1px solid var(--gray-200);
    text-align: left;
}

.pet-section h3,
.pet-section h4 {
    font-size: 0.74em;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--gray-500);
    margin-bottom: 7px;
}

.pet-notes {
    font-size: 0.88em;
    line-height: 1.5;
    color: var(--gray-700);
}

.pet-empty {
    font-size: 0.88em;
    color: var(--gray-500);
    font-style: italic;
}

/* A row, not a column: the text takes the space and the controls sit hard
   right, matching where the pen and cross sit on a card. */
.upcoming-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    margin-bottom: 7px;
    background: #eef2ff;
    border-left: 3px solid var(--primary-color);
    border-radius: 4px;
    font-size: 0.85em;
}

.upcoming-when {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1;
}

.upcoming-actions {
    display: flex;
    gap: 5px;
    margin-left: auto;
    flex-shrink: 0;
}

.upcoming-row span {
    color: var(--gray-700);
}

/* ==========================================================================
   Card hover icons (edit / remove)

   In site.css because the dog card is a shared partial used by more than one
   page — the same reason the modal and the pet-record styles live here.
   ========================================================================== */

.dog-card {
    position: relative;
}

.card-icons {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    gap: 6px;
    opacity: 0;
    transform: translateY(-3px);
    transition: opacity 0.16s ease, transform 0.16s ease;
    z-index: 2;
}

/* Revealed on hover, and whenever anything inside the card has focus, so the
   icons are reachable by keyboard as well as by mouse. */
.dog-card:hover .card-icons,
.dog-card:focus-visible .card-icons,
.dog-card:focus-within .card-icons {
    opacity: 1;
    transform: translateY(0);
}

.card-icon-btn {
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--gray-300);
    border-radius: 8px;
    background: white;
    color: var(--gray-700);
    cursor: pointer;
    box-shadow: var(--box-shadow);
    transition: var(--transition);
}

.card-icon-btn svg {
    width: 15px;
    height: 15px;
    display: block;
}

.card-icon-btn:hover:not(:disabled) {
    border-color: var(--primary-color);
    color: var(--primary-color);
    transform: scale(1.08);
}

.card-icon-btn.danger:hover:not(:disabled) {
    border-color: var(--danger-color);
    background: var(--danger-color);
    color: white;
}

.card-icon-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

/* Pets tab grid cells */
.dog-cell.hidden {
    display: none;
}

.dog-owner-link {
    display: inline-block;
    margin-bottom: 6px;
    font-size: 0.84em;
    font-weight: 600;
    color: var(--primary-color);
    text-decoration: none;
}

.dog-owner-link:hover {
    text-decoration: underline;
}

/* Small variant, for the icons on an appointment row */
.card-icon-btn.small {
    width: 24px;
    height: 24px;
    border-radius: 6px;
}

.card-icon-btn.small svg {
    width: 12px;
    height: 12px;
}

/* An upcoming appointment row lifts on hover and reveals its own controls */
.upcoming-row {
    transition: transform 0.16s ease, box-shadow 0.16s ease, background 0.16s ease;
}

.upcoming-row:hover {
    transform: translateY(-2px);
    background: #e6ebff;
    box-shadow: 0 6px 14px -6px rgba(17, 24, 39, 0.26);
}

.upcoming-actions {
    opacity: 0;
    transform: translateY(-2px);
    transition: opacity 0.16s ease, transform 0.16s ease;
}

.upcoming-row:hover .upcoming-actions,
.upcoming-row:focus-within .upcoming-actions {
    opacity: 1;
    transform: translateY(0);
}

/* ==========================================================================
   Pet profile photo
   ========================================================================== */

.dog-photo {
    position: relative;
    flex-shrink: 0;
    line-height: 0;
}

.dog-photo .dog-avatar {
    /* Uploaded photos are square JPEGs; drawn avatars are square SVGs. Both
       are cropped to the circle by the same rule. */
    object-fit: cover;
}

/* The camera sits over the picture, revealed on hover like the card icons */
.photo-upload {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(17, 24, 39, 0.55);
    color: white;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.16s ease;
}

.photo-upload svg {
    width: 40%;
    height: 40%;
}

.photo-upload input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.dog-photo.uploadable:hover .photo-upload,
.photo-upload:focus-within {
    opacity: 1;
}

.photo-upload:focus-within {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

/* Shown only when there is a photo to clear */
.photo-clear {
    position: absolute;
    top: -4px;
    right: -4px;
    width: 22px;
    height: 22px;
    border: 1px solid var(--gray-300);
    border-radius: 50%;
    background: white;
    color: var(--danger-color);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    box-shadow: var(--box-shadow);
    opacity: 0;
    transition: var(--transition);
}

.dog-photo.uploadable:hover .photo-clear,
.photo-clear:focus-visible {
    opacity: 1;
}

.photo-clear:hover {
    background: var(--danger-color);
    color: white;
}

.dog-photo.uploading .dog-avatar {
    opacity: 0.55;
}

/* The calendar panel's avatar is larger, so the camera scales with it */
#pet-photo-holder {
    margin: 0 auto 12px;
    width: 128px;
    height: 128px;
}

#pet-photo-holder .pet-avatar {
    margin: 0;
}

.photo-clear.hidden {
    display: none;
}

/* ==========================================================================
   Pet cards lift on hover

   Every pet card, not only the ones that open an editor: the lift says "this
   is one dog's record", and the pointer cursor is what says "clicking does
   something". Keeping the two separate means a read-only card still responds.
   ========================================================================== */

.dog-card,
.pet-card {
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.dog-card:hover,
.dog-card:focus-visible,
.pet-card:hover {
    transform: translateY(-4px);
    border-color: var(--primary-color);
    box-shadow: 0 12px 22px -8px rgba(17, 24, 39, 0.28),
                0 4px 8px -2px rgba(17, 24, 39, 0.12);
}

/* Only a card that actually opens something claims the pointer. */
.dog-card.editable {
    cursor: pointer;
}

.dog-card.editable:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

.dog-card.editable:active {
    transform: translateY(-1px);
}

/* The calendar's side-panel card is not a link, so no pointer — but it still
   lifts, and its own camera keeps working. */
.pet-card {
    border: 1px solid transparent;
    border-radius: var(--border-radius);
    padding: 4px;
}

/* Photo section inside the edit modal */
.edit-photo-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px;
    margin-bottom: 20px;
    background: var(--gray-50);
    border: 1px solid var(--gray-200);
    border-radius: var(--border-radius);
}

.edit-photo-row .dog-photo,
.edit-photo-row .dog-avatar {
    width: 86px;
    height: 86px;
    flex-shrink: 0;
}

.edit-photo-text {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.btn-small {
    padding: 5px 12px;
    font-size: 0.84em;
    align-self: flex-start;
    margin-top: 4px;
}

.btn-small.hidden {
    display: none;
}

/* --------------------------------------------------------------------------
   "Consult with our stylist" — the one deliberately showy control in the app.
   Lives here, not in a page stylesheet, because it sits in the shared
   appointment modal partial and so appears on every page that lists
   appointments.
   -------------------------------------------------------------------------- */

.btn-stylist {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    margin: 4px 0 18px;
    padding: 13px 22px;
    border: 0;
    border-radius: 999px;
    overflow: hidden;              /* keeps the shine inside the pill */
    cursor: pointer;
    text-decoration: none;
    font-size: 1.02em;
    font-weight: 700;
    letter-spacing: 0.015em;
    color: var(--brand-cream, #fdf9ee);
    background: linear-gradient(110deg,
        #6f7d43 0%, #97a85e 25%, #c9b273 50%, #836c4d 75%, #6f7d43 100%);
    background-size: 240% 100%;
    animation: stylist-drift 7s ease-in-out infinite;
    box-shadow: 0 6px 18px rgba(111, 125, 67, 0.32),
                inset 0 1px 0 rgba(255, 255, 255, 0.28);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.btn-stylist:hover,
.btn-stylist:focus-visible {
    transform: translateY(-2px) scale(1.012);
    box-shadow: 0 10px 26px rgba(111, 125, 67, 0.42),
                inset 0 1px 0 rgba(255, 255, 255, 0.34);
    color: #fff;
}

.btn-stylist:active {
    transform: translateY(0) scale(0.995);
}

.btn-stylist:focus-visible {
    outline: 2px solid var(--brand-cream, #fdf9ee);
    outline-offset: 2px;
}

/* The gradient slides so the pill looks lit from a moving source. */
@keyframes stylist-drift {
    0%, 100% { background-position: 0% 50%; }
    50%      { background-position: 100% 50%; }
}

/* A highlight that sweeps across every few seconds, and again on hover. */
.btn-stylist-shine {
    position: absolute;
    top: 0;
    left: -60%;
    width: 45%;
    height: 100%;
    pointer-events: none;
    background: linear-gradient(100deg,
        transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100%);
    transform: skewX(-18deg);
    animation: stylist-sweep 4.5s ease-in-out infinite;
}

@keyframes stylist-sweep {
    0%        { left: -60%; }
    55%, 100% { left: 130%; }
}

.btn-stylist:hover .btn-stylist-shine {
    animation-duration: 1.1s;
}

.btn-stylist-label {
    position: relative;            /* above the shine */
    display: inline-flex;
    align-items: center;
    gap: 9px;
    text-shadow: 0 1px 2px rgba(76, 66, 42, 0.35);
}

.btn-stylist-spark {
    width: 19px;
    height: 19px;
    flex: none;
    filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.75));
    animation: stylist-twinkle 2.4s ease-in-out infinite;
}

@keyframes stylist-twinkle {
    0%, 100% { opacity: 0.85; transform: scale(1) rotate(0deg); }
    50%      { opacity: 1;    transform: scale(1.14) rotate(8deg); }
}

.btn-stylist:hover .btn-stylist-spark {
    animation-duration: 1.2s;
}

/* Anyone who has asked the system to calm animations down gets a button that
   still reads as special, without the motion. */
@media (prefers-reduced-motion: reduce) {
    .btn-stylist,
    .btn-stylist-shine,
    .btn-stylist-spark {
        animation: none;
    }

    .btn-stylist {
        background-position: 30% 50%;
    }

    .btn-stylist-shine {
        display: none;
    }
}

/* --------------------------------------------------------------------------
   The stylist nav tab: the same treatment as the button, dialled down to sit
   in a row of plain links without shouting over the brand mark.
   -------------------------------------------------------------------------- */

.site-links a.nav-stylist {
    position: relative;
    display: inline-flex;
    align-items: center;
    overflow: hidden;
    border-radius: 999px;
    padding: 7px 15px;
    font-weight: 700;
    color: var(--brand-cream, #fdf9ee);
    background: linear-gradient(110deg,
        #6f7d43 0%, #97a85e 25%, #c9b273 50%, #836c4d 75%, #6f7d43 100%);
    background-size: 240% 100%;
    animation: stylist-drift 7s ease-in-out infinite;
    box-shadow: 0 2px 8px rgba(111, 125, 67, 0.28),
                inset 0 1px 0 rgba(255, 255, 255, 0.26);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

/* Beats `.site-links a:hover` and `.site-links a.active`, both of which would
   otherwise flatten the gradient to a solid colour. */
.site-links a.nav-stylist:hover,
.site-links a.nav-stylist:focus-visible,
.site-links a.nav-stylist.active {
    color: #fff;
    background: linear-gradient(110deg,
        #6f7d43 0%, #97a85e 25%, #c9b273 50%, #836c4d 75%, #6f7d43 100%);
    background-size: 240% 100%;
}

.site-links a.nav-stylist:hover,
.site-links a.nav-stylist:focus-visible {
    transform: translateY(-1px);
    box-shadow: 0 5px 14px rgba(111, 125, 67, 0.4),
                inset 0 1px 0 rgba(255, 255, 255, 0.32);
}

/* The current page gets a ring instead of extra motion, so "you are here"
   still reads at a glance. An outline, not another box-shadow ring - the
   pill's own overflow:hidden (needed to clip the shine sweep inside it)
   clips box-shadow too, but not an outline, which is what made the ring
   look thicker on some sides than others. */
.site-links a.nav-stylist.active {
    box-shadow: 0 2px 10px rgba(111, 125, 67, 0.34),
                inset 0 1px 0 rgba(255, 255, 255, 0.3);
    outline: 2px solid var(--brand-cream, #fdf9ee);
    outline-offset: 1.5px;
}

.nav-stylist-shine {
    position: absolute;
    top: 0;
    left: -60%;
    width: 40%;
    height: 100%;
    pointer-events: none;
    background: linear-gradient(100deg,
        transparent 0%, rgba(255, 255, 255, 0.5) 50%, transparent 100%);
    transform: skewX(-18deg);
    animation: stylist-sweep 5.5s ease-in-out infinite;
}

.site-links a.nav-stylist:hover .nav-stylist-shine {
    animation-duration: 1.1s;
}

.nav-stylist-label {
    position: relative;            /* above the shine */
    display: inline-flex;
    align-items: center;
    gap: 7px;
    white-space: nowrap;
    text-shadow: 0 1px 2px rgba(76, 66, 42, 0.3);
}

.nav-stylist-spark {
    width: 14px;
    height: 14px;
    flex: none;
    filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.7));
    animation: stylist-twinkle 2.8s ease-in-out infinite;
}

.site-links a.nav-stylist:hover .nav-stylist-spark {
    animation-duration: 1.2s;
}

@media (prefers-reduced-motion: reduce) {
    .site-links a.nav-stylist,
    .nav-stylist-shine,
    .nav-stylist-spark {
        animation: none;
    }

    .site-links a.nav-stylist {
        background-position: 30% 50%;
    }

    .nav-stylist-shine {
        display: none;
    }
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    background: white;
    border-radius: var(--border-radius);
    overflow: hidden;
    box-shadow: var(--box-shadow);
}

.data-table th,
.data-table td {
    text-align: left;
    padding: 10px 14px;
    border-bottom: 1px solid #eee;
}

.data-table th {
    background: #f7f7f2;
    font-weight: 700;
}

/* ==========================================================================
   Tabs: a reusable bar + panel pair (e.g. Projects' three lists)
   ========================================================================== */

.tab-bar {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--gray-200);
    margin-bottom: 20px;
    overflow-x: auto;
    scrollbar-width: none;
}

.tab-bar::-webkit-scrollbar {
    display: none;
}

.tab-btn {
    flex-shrink: 0;
    padding: 10px 16px;
    border: none;
    background: none;
    font-size: 0.95em;
    font-weight: 600;
    color: var(--gray-500);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
}

.tab-btn:hover {
    color: var(--gray-900);
}

.tab-btn.active {
    color: var(--primary-color);
    border-bottom-color: var(--primary-color);
}

.tab-panel.hidden {
    display: none;
}

/* ==========================================================================
   Nav "More" dropdown
   ========================================================================== */

.nav-more {
    position: relative;
    flex-shrink: 0;
}

.nav-more-toggle {
    padding: 7px 14px;
    border-radius: 6px;
    border: none;
    background: none;
    color: var(--gray-700);
    font-weight: 500;
    font-size: 0.95em;
    cursor: pointer;
    white-space: nowrap;
}

.nav-more-toggle:hover,
.nav-more-toggle.active {
    background: color-mix(in srgb, var(--primary-color) 20%, white);
    color: var(--primary-color);
}

.nav-more-caret {
    font-size: 0.8em;
}

.nav-more-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    background: white;
    border: 1px solid var(--gray-200);
    border-radius: var(--border-radius);
    box-shadow: var(--box-shadow);
    display: flex;
    flex-direction: column;
    min-width: 160px;
    z-index: 60;
    padding: 6px;
}

.nav-more-menu.hidden {
    display: none;
}

/* The account dropdown sits at the far right of the nav - opening
   toward the left (the default, matching "More") would push its menu
   off the right edge of the viewport. */
#nav-account .nav-more-menu {
    left: auto;
    right: 0;
}

.site-user-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.nav-more-menu a {
    padding: 8px 12px;
    border-radius: 6px;
    color: var(--gray-700);
    text-decoration: none;
    font-weight: 500;
    font-size: 0.95em;
    white-space: nowrap;
}

.nav-more-menu a:hover {
    background: var(--gray-100);
}

.nav-more-menu a.active {
    background: color-mix(in srgb, var(--primary-color) 20%, white);
    color: var(--primary-color);
}
