/* ---------------------------------------------------------------------------
   pedgree project styles.

   Colour comes exclusively from the --pg-* custom properties emitted per
   request by Project::headHtml(), so a club's branding flows through here
   without this file knowing anything about any particular club. Never hardcode
   a brand colour below — add a token instead.

   Everything structural (spacing, typography, controls, tables) stays with
   base.css; this file only adds what the framework has no opinion about.

   THEMES. The framework's themes are stylesheets (default / midnight / sepia),
   chosen per user, and midnight is dark. Nothing here may assume a light page.
   Two rules follow from that:

     - Never state a background or a tint flat. Derive it from the theme's own
       --bspkfw-field-surface (--pg-surface wraps it), so the tint follows the
       page rather than fighting it.
     - Where a hue has to be preserved for meaning (the titled-dog red), mix it
       toward --bspkfw-field-text, which is by definition the colour that reads
       against the current background.

   The --pg-*-soft tokens already do the first of these — see ClubTheme::softMix.
   --------------------------------------------------------------------------- */

/* --- Club-coloured header -------------------------------------------------
   The framework's .site-header is a hardcoded slate (#1e293b) with no token to
   hook, so the club's primary is applied here instead — pedgree.css loads after
   base.css, and these selectors match the framework's own specificity, so the
   later file wins without an !important anywhere.

   Foreground comes from --pg-primary-ink, never a fixed white: ClubTheme picks
   that by WCAG contrast against the chosen primary, so a club that picks a pale
   colour gets dark header text instead of white-on-cream. Every value keeps the
   framework's original as its var() fallback, so a page rendered without the
   theme block (or a future host with no club at all) still looks deliberate
   rather than unstyled.
   ------------------------------------------------------------------------- */

.site-header {
    background: var(--pg-primary, #1e293b);
    color: var(--pg-primary-ink, #f8fafc);
}

/* These set their own colour in base.css, so inheriting from .site-header is
   not enough — they have to be named. */
.site-title,
.site-nav-main-item,
.site-nav-main-trigger,
.user-menu-trigger {
    color: var(--pg-primary-ink, #f8fafc);
}

/* Idle nav items sat one step down from the title in the original palette
   (#cbd5e1 against #f8fafc). Expressed as opacity rather than a second colour
   so it holds against any primary, light or dark. */
.site-nav-main-item { opacity: 0.82; }

.site-nav-main-item:hover,
.site-nav-main-item:focus-visible,
.site-nav-main-item.is-active,
.site-nav-main-trigger.is-active {
    opacity: 1;
    color: var(--pg-primary-ink, #f8fafc);
    /* Was a fixed lighter slate (#334155), which only reads as "raised" on a
       dark header. A translucent wash of the ink colour lifts against a dark
       primary and deepens against a light one. */
    background: color-mix(in srgb, var(--pg-primary-ink, #f8fafc) 16%, transparent);
}

/* Deliberately untouched: .site-nav-dropdown is a white panel hanging BELOW the
   header with its own dark text. It is not on the coloured bar, and tinting it
   would cost the contrast base.css already gets right. */

/* --- Club identity ------------------------------------------------------- */

.pg-club-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 600;
    /* Lets the name below shrink; without it a flex item refuses to go under
       its content width and the brand pushes the header chrome sideways. */
    min-width: 0;
}

/* Centre the brand against the header rather than against the TEXT BASELINE.
 *
 * .pg-club-brand is inline-flex, so in an ordinary line box it sits on the
 * baseline — and because its first flex item is an <img> with no baseline of
 * its own, the browser synthesises one from the box's bottom edge. The brand's
 * bottom therefore lands on the baseline, leaving the strut's descender space
 * (~4px) empty beneath it, and the logo rides that much above centre. It only
 * shows up WITH a logo: Project::brandHtml() returns a bare name otherwise,
 * and plain text sits on the same baseline as everything else.
 *
 * Making .site-title a flex container takes the baseline out of it entirely.
 * Scoped with :has() so the text-only case keeps the framework's own layout —
 * that matters, because .site-title carries deliberate
 * overflow/text-overflow/white-space truncation that only works in an inline
 * formatting context, and flexing it unconditionally would silently drop the
 * ellipsis on every install without a logo. Where :has() is unsupported the
 * rule is skipped and the header simply looks as it does today.
 */
.site-title:has(.pg-club-brand) {
    display: flex;
    align-items: center;
}

/* Truncation moves onto the name, which is the part that should give. */
.pg-club-brand > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pg-club-brand__logo {
    height: 1.75rem;
    width: auto;
    max-width: 10rem;
    object-fit: contain;
    /* The logo keeps its size and the name ellipses — squashing a club's mark
       to fit a long name gets the priority backwards. */
    flex: none;
}

/* --- Hero / page intro --------------------------------------------------- */

.pg-hero {
    background: var(--pg-primary);
    color: var(--pg-primary-ink);
    border-radius: var(--bspkfw-field-radius, 8px);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}

/* With a logo the hero becomes a row: mark on the left, name and greeting on
   the right — the same reading order as the header, so the two agree. */
.pg-hero--branded {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.pg-hero__logo {
    height: 4rem;
    width: auto;
    max-width: 12rem;
    object-fit: contain;
    /* The name gives before the mark does, exactly as in the header. */
    flex: none;
}

/* min-width:0 so a long club name wraps inside the flex row instead of
   forcing the hero wider than its column. */
.pg-hero__text { min-width: 0; }

@media (max-width: 30rem) {
    /* At phone width a 4rem mark beside wrapping text leaves neither enough
       room; stack instead, and let the mark lead. */
    .pg-hero--branded {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.75rem;
    }
}

.pg-hero__title {
    margin: 0 0 0.25rem;
    font-size: 1.5rem;
    line-height: 1.2;
}

.pg-hero__subtitle {
    margin: 0;
    opacity: 0.85;
}

/* --- Completeness indicator ---------------------------------------------- */

/* The green tick that marks a record with everything its club asks for.
   It follows the NAME wherever a name is rendered — pedigree boxes, the record
   header, the public page and the builder's search results — so that a name on
   its own still says whether the record behind it is finished. Defined once
   here; the markup comes from PedigreeChart::tick() server-side and
   completeTick() in pedigree-builder.js, which mirror each other. */
.pg-complete,
.pg-incomplete {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15em;
    height: 1.15em;
    border-radius: 50%;
    font-size: 0.85em;
    line-height: 1;
    vertical-align: middle;
}

.pg-complete {
    background: #17803D;
    color: #FFFFFF;
}

/* Sits against the name it belongs to, and never wraps away from it onto a
   line of its own — a tick orphaned under a name reads as a separate fact. */
.pg-box__name .pg-complete,
.pg-animal__name .pg-complete,
.pg-public__name .pg-complete,
.pg-suggest__name .pg-complete {
    margin-left: 0.35em;
    flex: none;
}

/* The headings are large; the mark should read as a mark, not as punctuation
   scaled up to match. */
.pg-animal__name .pg-complete,
.pg-public__name .pg-complete {
    font-size: 0.5em;
    width: 1.4em;
    height: 1.4em;
    vertical-align: 0.35em;
}

/* Deliberately quiet: an incomplete record is the normal state during data
   entry, not an error. It reads as "not yet", not as a failure. */
.pg-incomplete {
    background: transparent;
    border: 1px dashed currentColor;
    opacity: 0.4;
}

/* --- Cards --------------------------------------------------------------- */

.pg-card {
    border: 1px solid var(--bspkfw-field-border, #d4d4d8);
    border-radius: var(--bspkfw-field-radius, 8px);
    padding: 1rem;
    background: var(--bspkfw-field-surface, #ffffff);
}

.pg-card__title {
    margin: 0 0 0.5rem;
    font-size: 1rem;
    font-weight: 600;
}

.pg-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 1rem;
}

/* --- Stat tiles ---------------------------------------------------------- */

.pg-stat {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.pg-stat__value {
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1;
    color: var(--pg-primary);
}

.pg-stat__label {
    font-size: 0.875rem;
    opacity: 0.7;
}

/* --- Empty / notice states ----------------------------------------------- */

.pg-notice {
    border-left: 3px solid var(--pg-accent);
    background: var(--pg-accent-soft);
    padding: 0.75rem 1rem;
    border-radius: 0 var(--bspkfw-field-radius, 8px) var(--bspkfw-field-radius, 8px) 0;
}

/* ---------------------------------------------------------------------------
   Pedigree chart.

   Layout is nested rather than a CSS grid: each node is [box][its two parents],
   and a column of two children is naturally twice the height of one. That gives
   the bracket proportions for free at any depth — and, crucially, needs no
   per-box positioning, so nothing here requires an inline style (which the CSP
   would block anyway).
   --------------------------------------------------------------------------- */

.pg-ped {
    --pg-col-w: 13rem;
    --pg-connector: 1.5rem;
    --pg-line: var(--bspkfw-field-border, #d4d4d8);
    display: flex;
    /* Six generations is 126 boxes; it will not fit any screen, so the chart
       scrolls inside its own container rather than forcing the page sideways. */
    overflow-x: auto;
    padding: 0.5rem 0;
}

.pg-node {
    display: flex;
    align-items: center;
}

.pg-parents {
    display: flex;
    flex-direction: column;
    position: relative;
    margin-left: var(--pg-connector);
}

/* Vertical spine linking the two parents, spanning between their centres. */
.pg-parents::before {
    content: '';
    position: absolute;
    left: calc(var(--pg-connector) / -2);
    top: 25%;
    bottom: 25%;
    border-left: 1px solid var(--pg-line);
}

/* --- Boxes --------------------------------------------------------------- */

.pg-box {
    position: relative;
    flex: 0 0 var(--pg-col-w);
    box-sizing: border-box;
    min-height: 2.75rem;
    margin: 0.15rem 0;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--pg-line);
    border-radius: var(--bspkfw-field-radius, 6px);
    background: var(--bspkfw-field-surface, #fff);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.1rem;
    font-size: 0.85rem;
    line-height: 1.25;
    text-align: left;
}

/* Horizontal stub from the spine into each parent box. */
.pg-parents > .pg-node > .pg-box::before {
    content: '';
    position: absolute;
    right: 100%;
    top: 50%;
    width: calc(var(--pg-connector) / 2);
    border-top: 1px solid var(--pg-line);
}

/* Stub from a box out to its own parents' spine. */
.pg-box--branch::after {
    content: '';
    position: absolute;
    left: 100%;
    top: 50%;
    width: calc(var(--pg-connector) / 2);
    border-top: 1px solid var(--pg-line);
}

.pg-box--subject {
    border-color: var(--pg-primary);
    border-width: 2px;
}

/* Sire above, dam below — tinted just enough to read the halves apart at a
   glance without turning the chart into a colour chart. */
.pg-box--male   { border-left: 3px solid color-mix(in srgb, #2F6FB5 55%, var(--pg-line)); }
.pg-box--female { border-left: 3px solid color-mix(in srgb, #B5427A 45%, var(--pg-line)); }

.pg-box--empty {
    background: transparent;
    border-style: dashed;
    opacity: 0.55;
}

.pg-box__name { font-weight: 600; }

/* Titled dogs print in red. This is the convention on Kennel Club and PTCA
   pedigrees, carried onto the screen so what you see matches what you issue.

   Mixed toward the theme's TEXT colour rather than stated flat, so the hue
   survives while the lightness follows the page. Kennel Club red on its own is
   dark enough to read as near-black against a dark theme, which loses the one
   thing the colour is there to say. Mixing toward the text colour moves it the
   right way in both directions: darker on a light page, lighter on a dark one,
   because that colour is by definition the legible one. */
.pg-box.is-titled .pg-box__name {
    color: color-mix(in srgb, #B3261E 78%, var(--bspkfw-field-text, #111111));
}

.pg-box__reg,
.pg-box__year {
    font-size: 0.75rem;
    opacity: 0.7;
}

.pg-box .pg-complete {
    position: absolute;
    top: 0.3rem;
    right: 0.3rem;
    font-size: 0.7rem;
}

/* --- Empty slot as a control (builder) ----------------------------------- */

.pg-box--add {
    cursor: pointer;
    align-items: center;
    color: inherit;
    font: inherit;
}

.pg-box--add:hover,
.pg-box--add:focus-visible {
    border-color: var(--pg-primary);
    opacity: 1;
}

.pg-box__add-label { font-size: 0.8rem; opacity: 0.8; }

/* --- Repeated ancestors --------------------------------------------------
   A stable colour per repeated animal, painted as a tab on the box edge, so
   the same dog can be paired by eye across a chart too wide to scan.
   ------------------------------------------------------------------------- */

.pg-ped[data-duplicates="off"] .is-duplicate::after,
.pg-ped[data-duplicates="off"] .pg-dupe-tab { display: none; }

.is-duplicate {
    border-right-width: 4px;
    border-right-style: solid;
}

[data-duplicate="0"] { border-right-color: #E8743B; }
[data-duplicate="1"] { border-right-color: #19A979; }
[data-duplicate="2"] { border-right-color: #945ECF; }
[data-duplicate="3"] { border-right-color: #13A4B4; }
[data-duplicate="4"] { border-right-color: #C7B42C; }
[data-duplicate="5"] { border-right-color: #BD3861; }
[data-duplicate="6"] { border-right-color: #6C8893; }
[data-duplicate="7"] { border-right-color: #EF5D9E; }

.pg-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.75rem;
    font-size: 0.8rem;
}

.pg-legend__label { opacity: 0.7; }

.pg-legend__item {
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--pg-line);
    border-right-width: 4px;
    border-right-style: solid;
}

/* --- Chart toolbar ------------------------------------------------------- */

.pg-chart-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}

.pg-chart-toolbar__group {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

/* --- Responsive ---------------------------------------------------------- */

@media (max-width: 1024px) {
    .pg-ped { --pg-col-w: 11rem; --pg-connector: 1rem; }
}

@media (max-width: 700px) {
    /* Boxes narrow and the chart scrolls, rather than shrinking text to
       illegibility. Members enter dogs at shows on a phone, so the near
       generations must stay readable even when the far ones are off-screen. */
    .pg-ped { --pg-col-w: 9.5rem; --pg-connector: 0.75rem; }
    .pg-box { font-size: 0.8rem; min-height: 2.4rem; }
}

/* --- Print --------------------------------------------------------------- */

@media print {
    .pg-chart-toolbar,
    .pg-box--add { display: none; }

    .pg-ped {
        --pg-col-w: 8rem;
        --pg-connector: 0.6rem;
        overflow: visible;
    }

    .pg-box {
        font-size: 0.7rem;
        /* Colour is meaning here — titled dogs and repeated ancestors — so ask
           the browser not to drop it from the printed page. */
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}

/* ---------------------------------------------------------------------------
   Animal record page.
   --------------------------------------------------------------------------- */

.pg-animal__header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 1rem;
    margin-bottom: 1rem;
}

.pg-animal__name {
    margin: 0;
    font-size: 1.6rem;
    line-height: 1.15;
}

/* Titles are part of the name on a pedigree, and titled dogs print in red —
   the same convention the chart follows. */
.pg-animal__call {
    margin: 0;
    opacity: 0.75;
    font-style: italic;
}

.pg-animal__complete,
.pg-animal__incomplete {
    margin: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.875rem;
}

.pg-animal__incomplete { opacity: 0.8; }

.pg-animal__actions {
    margin-left: auto;
    display: flex;
    gap: 0.5rem;
}

.pg-animal__pedigree { margin-bottom: 1.5rem; }

/* Header action above a manage grid. Right-aligned so it reads as a page-level
   action rather than something belonging to the first row of the table. */
.pg-manage-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.pg-animal__panels { align-items: start; }

/* --- Relations + details -------------------------------------------------- */

.pg-relation__heading {
    margin: 0.75rem 0 0.35rem;
    font-size: 0.9rem;
    font-weight: 600;
    opacity: 0.8;
}

.pg-relation__heading:first-of-type { margin-top: 0; }

.pg-relation__list {
    margin: 0;
    padding-left: 1.1rem;
}

.pg-relation__list li { margin-bottom: 0.2rem; }

.pg-details {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.3rem 1rem;
    margin: 0;
}

.pg-details dt {
    font-weight: 600;
    opacity: 0.7;
    font-size: 0.85rem;
}

.pg-details dd { margin: 0; }

.pg-muted {
    opacity: 0.65;
    font-size: 0.875rem;
    margin: 0;
}

/* --- QR panel ------------------------------------------------------------- */

.pg-animal__qr { text-align: center; }

.pg-qr {
    display: flex;
    justify-content: center;
    margin-bottom: 0.5rem;
}

/* The generated SVG has no intrinsic sizing of its own. */
.pg-qr svg {
    width: 160px;
    height: 160px;
    max-width: 100%;
}

.pg-qr__url {
    font-size: 0.75rem;
    word-break: break-all;
    margin: 0.35rem 0 0;
}

/* --- Re-rooted banner ----------------------------------------------------- */

.pg-rooted {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}

.pg-rooted__reset { margin-left: auto; }

/* The step-back arrow leads the bar, so the way back is the first thing on the
   line rather than something to hunt for at the end. Square and compact — it is
   an icon control, and padding sized for a word makes it read as a button whose
   label failed to load. */
.pg-rooted__step {
    flex: none;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    line-height: 1;
}

/* --- Re-root travel ------------------------------------------------------
   Re-rooting is MOVEMENT ALONG one pedigree, not the arrival of an unrelated
   dog's chart, and a plain swap reads as the latter. So the tree slides in the
   direction travelled: choosing an ancestor walks rightward along the pedigree,
   so the chart leaves to the LEFT and the new one arrives from the right;
   "back to subject" reverses it.

   Short and shallow on purpose — this is a hint about direction, not a
   transition to sit through. The out leg is quicker than the in leg so the wait
   is front-loaded and the arrival feels settled.
   ------------------------------------------------------------------------- */

/* Clip only while travelling: .pg-ped keeps its own overflow-x for the six-
   generation case, and clipping the wrapper permanently would fight it. */
[data-pg-chart].pg-ped-anim { overflow: hidden; }

@keyframes pg-ped-out-left  { to   { transform: translateX(-7%); opacity: 0; } }
@keyframes pg-ped-in-right  { from { transform: translateX(7%);  opacity: 0; } }
@keyframes pg-ped-out-right { to   { transform: translateX(7%);  opacity: 0; } }
@keyframes pg-ped-in-left   { from { transform: translateX(-7%); opacity: 0; } }

.pg-ped-out-left  { animation: pg-ped-out-left  160ms ease-in forwards; }
.pg-ped-out-right { animation: pg-ped-out-right 160ms ease-in forwards; }
.pg-ped-in-right  { animation: pg-ped-in-right  240ms ease-out; }
.pg-ped-in-left   { animation: pg-ped-in-left   240ms ease-out; }

@media (prefers-reduced-motion: reduce) {
    /* Belt and braces — the JS checks the same query and takes the plain
       spinner path, so these should never be applied in the first place. */
    .pg-ped-out-left,
    .pg-ped-out-right,
    .pg-ped-in-right,
    .pg-ped-in-left { animation: none; }
}

/* Sits between the chart and the panels it is talking about. Same accent
   treatment as the re-root banner above the chart, so the two read as one
   state rather than two unrelated messages. */
.pg-animal__subject-note {
    margin: 0 0 1rem;
}

@media print {
    .pg-animal__actions,
    .pg-rooted,
    .pg-animal__qr { display: none; }
}

/* ---------------------------------------------------------------------------
   Quick-entry builder.
   --------------------------------------------------------------------------- */

.pg-builder__header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 1rem;
}

.pg-builder__header h1 { margin: 0; font-size: 1.4rem; }
.pg-builder__actions { margin-left: auto; }
.pg-builder__hint { margin: 0.25rem 0 1rem; max-width: 60ch; }

.pg-builder-start { max-width: 40rem; }
.pg-builder-start .pg-card { margin-bottom: 1rem; }

/* --- Save state ----------------------------------------------------------
   Deliberately quiet. Every slot writes as it is filled, so this reports a
   fact rather than prompting an action; anything louder would read as an
   unsaved-changes warning that is never true.
   ------------------------------------------------------------------------- */

.pg-save-state {
    margin-left: auto;
    font-size: 0.8rem;
    opacity: 0.6;
}

.pg-save-state.is-busy { opacity: 1; }

/* --- Slot editor ---------------------------------------------------------- */

.pg-box--editing {
    overflow: visible;
    z-index: 5;
    border-color: var(--pg-primary);
    border-width: 2px;
}

.pg-slot-input {
    width: 100%;
    box-sizing: border-box;
    font-size: 0.85rem;
    padding: 0.2rem 0.35rem;
}

/* --- Suggestions ---------------------------------------------------------
   Anchored out of the box's flow: the chart's rows are only as tall as a box,
   so an in-flow dropdown would either clip or shove the whole bracket apart.
   ------------------------------------------------------------------------- */

.pg-box--editing .pg-suggest {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 100%;
    width: max-content;
    max-width: 22rem;
    z-index: 20;
}

/* Wraps the search input alone so the dropdown can hang off the FIELD rather
   than off the form-group, whose help text, error slot and bottom margin would
   otherwise sit between the two. */
.pg-suggest-anchor { position: relative; }

.pg-suggest-anchor .pg-suggest {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    right: 0;
    z-index: 20;
}

.pg-suggest {
    display: flex;
    flex-direction: column;
    background: var(--bspkfw-field-surface, #fff);
    border: 1px solid var(--pg-line, #d4d4d8);
    border-radius: var(--bspkfw-field-radius, 6px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
    /* Browsing returns up to 25, so the list scrolls rather than running off
       the bottom of the viewport. overflow-x stays hidden to keep the corners. */
    max-height: 18rem;
    overflow-y: auto;
    overflow-x: hidden;
}

.pg-suggest:empty { display: none; }

/* `display` on the class above beats the [hidden] attribute's UA rule, so the
   attribute alone cannot hide a list that still has children. Restate it. */
.pg-suggest[hidden] { display: none; }

.pg-suggest__item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
    padding: 0.4rem 0.6rem;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.pg-suggest__item:hover,
.pg-suggest__item.is-active {
    background: var(--pg-primary-soft, #eef2ff);
}

.pg-suggest__name { font-weight: 600; font-size: 0.85rem; }
.pg-suggest__meta { opacity: 0.7; font-size: 0.75rem; }

/* The create row is the fallback, not the default — set apart so picking an
   existing dog stays the obvious choice, since that is what inherits ancestry. */
.pg-suggest__create {
    border-top: 1px solid var(--pg-line, #d4d4d8);
    font-size: 0.82rem;
    opacity: 0.9;
}

/* Quieter still than the create row: entering an ancestor in full is the
   exception during a bulk session, so it should be findable without competing
   with the one-keystroke path above it. */
.pg-suggest__details {
    border-top: 1px solid var(--pg-line, #d4d4d8);
    flex-direction: row;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    opacity: 0.75;
}

.pg-suggest__details::before {
    content: "＋";
    font-size: 0.85rem;
    line-height: 1;
}

.pg-suggest__details:hover,
.pg-suggest__details.is-active { opacity: 1; }

/* --- Secondary action under a card's primary form -------------------------- */

.pg-card__aside {
    margin-top: 0.9rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--pg-line, #d4d4d8);
}

.pg-card__aside-help {
    margin: 0.4rem 0 0;
    font-size: 0.8rem;
}

/* --- Uploaded imagery ------------------------------------------------------ */

.pg-animal__photo {
    width: 4.5rem;
    height: 4.5rem;
    object-fit: cover;
    border-radius: var(--bspkfw-field-radius, 8px);
    border: 1px solid var(--bspkfw-field-border, #d4d4d8);
    flex: 0 0 auto;
}

/* ---------------------------------------------------------------------------
   Public lineage page (the QR target).

   Mobile-first by necessity: this is opened by scanning a printed certificate,
   which means a phone, usually held at a kennel or a show rather than a desk.
   --------------------------------------------------------------------------- */

.pg-public {
    max-width: 60rem;
    margin: 0 auto;
}

.pg-public__header {
    text-align: center;
    padding-bottom: 1rem;
    border-bottom: 2px solid var(--pg-primary);
    margin-bottom: 1.25rem;
}

.pg-public__logo {
    max-height: 4rem;
    max-width: 60%;
    width: auto;
    object-fit: contain;
    margin-bottom: 0.5rem;
}

.pg-public__club {
    margin: 0;
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.7;
}

.pg-public__name {
    margin: 0.25rem 0 0;
    font-size: 1.5rem;
    line-height: 1.15;
}

.pg-public__call {
    margin: 0.15rem 0 0;
    font-style: italic;
    opacity: 0.75;
}

.pg-public__facts {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.3rem 1rem;
    margin: 0 0 1.5rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--bspkfw-field-border, #d4d4d8);
    border-radius: var(--bspkfw-field-radius, 8px);
}

.pg-public__facts dt {
    font-weight: 600;
    font-size: 0.85rem;
    opacity: 0.7;
}

.pg-public__facts dd { margin: 0; }

.pg-public__pedigree h2 {
    font-size: 1rem;
    margin: 0 0 0.5rem;
}

.pg-public__footer {
    margin-top: 1.5rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--bspkfw-field-border, #d4d4d8);
    font-size: 0.85rem;
}

.pg-public__footer p { margin: 0 0 0.2rem; }

@media (max-width: 700px) {
    .pg-public__facts { grid-template-columns: 1fr; gap: 0.1rem; }
    .pg-public__facts dt { margin-top: 0.4rem; }
}

/* --- Platform console ------------------------------------------------------ */

.pg-console__totals { margin-bottom: 1.5rem; }
.pg-console__clubs  { margin-bottom: 1.5rem; }
.pg-console__create { max-width: 40rem; }

.pg-console__create .pg-notice { margin-bottom: 1rem; }

/* --- Club dashboard -------------------------------------------------------- */

.pg-dashboard__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1.25rem;
}

.pg-dashboard__search { margin-bottom: 1.25rem; max-width: 34rem; }
.pg-dashboard__stats  { margin-bottom: 1.25rem; }

/* Sits above the stats in reading order only when there is something to act
   on — the panel is omitted entirely otherwise. */
.pg-dashboard__attention { margin-bottom: 1.25rem; }
.pg-dashboard__attention p { margin: 0 0 0.4rem; }
.pg-dashboard__attention p:last-child { margin-bottom: 0; }

.pg-dashboard__recent ul {
    margin: 0;
    padding-left: 1.1rem;
}

.pg-dashboard__recent li { margin-bottom: 0.2rem; }

/* --- Certificates ---------------------------------------------------------- */

.pg-cert-list { margin: 0 0 0.75rem; padding-left: 1.1rem; }
.pg-cert-list li { margin-bottom: 0.25rem; }
.pg-cert__serial { font-weight: 600; }

.pg-cert-issue {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--bspkfw-field-border, #d4d4d8);
}

.pg-cert-issue .pg-muted { flex-basis: 100%; margin: 0; }

/* --- Planned mating -------------------------------------------------------
   Two pickers side by side so a pairing reads as one decision, stacking on a
   phone where they would otherwise be two half-width dropdowns.
   ------------------------------------------------------------------------- */

.pg-mating__fields {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.pg-mating__fields > * {
    flex: 1 1 14rem;
    min-width: 0;
}

/* The figure is the answer, so it carries the weight of one — but not so much
   that it reads as a verdict. The ancestors beneath it are the actionable half. */
.pg-mating__figure {
    font-size: 1.25rem;
    font-weight: 600;
    margin: 0 0 0.75rem;
}

/* --- Health results -------------------------------------------------------
   One line per test, the result carrying the weight. Only genetic results are
   colour-coded: a hip score means nothing without the breed's median beside
   it, and colouring one would assert a judgement this project cannot make.
   ------------------------------------------------------------------------- */

.pg-health { list-style: none; margin: 0; padding: 0; }

.pg-health__row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--pg-line, #e5e7eb);
}

.pg-health__row:last-child { border-bottom: 0; }

.pg-health__test { flex: 1 1 10rem; min-width: 0; }

.pg-health__result {
    font-weight: 600;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
}

.pg-health__date { opacity: 0.7; font-size: 0.85rem; }

/* Clear / carrier / affected. Carrier is deliberately NOT a warning colour —
   a carrier is a perfectly breedable dog given a clear mate, and colouring it
   as a problem is how a register loses good stock to a traffic light. */
.pg-health__result.is-clear    { background: #E3F2E8; color: #17803D; }
.pg-health__result.is-carrier  { background: #FFF6DF; color: #8A6100; }
.pg-health__result.is-affected { background: #FBE4E2; color: #B3261E; }
