/* ==========================================================================
   Designer Flair - reusable components
   ========================================================================== */

/* ---- Logo / wordmark ----------------------------------------------------
   The Designer Flair mark, matched to the script on the printed business card:
   "Designer Flair" set as one continuous gold script.

   It is live text rather than an image, so it stays perfectly sharp at every
   size and Google and screen readers can read the business name. The script
   has a small x-height, so it is set larger than a serif would be to read at
   the same optical size.

   THIS IS THE ONLY PLACE THE MARK IS STYLED. If an original logo file turns
   up later, swap the markup in Logo.razor and nothing else changes.           */

.logo {
    display: inline-block;
    font-family: var(--font-logo);
    font-weight: 700;
    font-size: clamp(1.75rem, 1.35rem + 1.6vw, 2.4rem);
    line-height: 1;
    /* The script's own slant leaves a gap on the right; nudge it back. */
    letter-spacing: .004em;
    padding-right: .06em;
    text-decoration: none;
    white-space: nowrap;
    color: var(--gold-logo-on-light);
    transition: color var(--transition);
}

/* Light variant, for the black footer, dark panel and transparent header.
   The printed card sets the gold script inside a dark outline; repeating that
   here keeps the mark faithful and, on the hero, lifts it off the photograph. */
.logo--light {
    color: var(--gold-logo-on-dark);
    -webkit-text-stroke: 3px rgba(10, 9, 7, .92);
    paint-order: stroke fill;
}

.logo--lg {
    font-size: clamp(2.1rem, 1.6rem + 2vw, 3rem);
}

/* ---- Buttons ------------------------------------------------------------ */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .625rem;
    /* Comfortable touch target on every device. */
    min-height: 52px;
    padding: .95rem 2rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-size: var(--fs-small);
    font-weight: 600;
    letter-spacing: var(--ls-button);
    text-transform: uppercase;
    text-decoration: none;
    text-align: center;
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition),
                border-color var(--transition), transform var(--transition);
}

.btn:active {
    transform: translateY(1px);
}

.btn--primary {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--ink);
}

.btn--primary:hover {
    background: #b58f47;
    border-color: #b58f47;
}

/* Outlined gold, used beside the primary button on dark imagery. */
.btn--ghost {
    background: transparent;
    border-color: var(--gold);
    color: #fff;
}

.btn--ghost:hover {
    background: var(--gold);
    color: var(--ink);
}

/* Outlined dark, for use on light backgrounds. */
.btn--outline {
    background: transparent;
    border-color: var(--ink);
    color: var(--ink);
}

.btn--outline:hover {
    background: var(--ink);
    color: #fff;
}

.btn--block {
    width: 100%;
}

.btn[disabled],
.btn[aria-disabled="true"] {
    opacity: .6;
    cursor: not-allowed;
    pointer-events: none;
}

.btn-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
}

/* WhatsApp action - present but deliberately quiet. */
.btn--whatsapp {
    background: transparent;
    border-color: var(--line-strong);
    color: var(--ink);
}

.btn--whatsapp:hover {
    border-color: var(--ink);
    background: var(--ink);
    color: #fff;
}

.btn--whatsapp svg {
    width: 18px;
    height: 18px;
    flex: none;
}

/* ---- Floating WhatsApp icon ----------------------------------------------
   Just the WhatsApp mark, pinned bottom-right. It stays visible the whole way
   down the page: it used to fade out as soon as the visitor scrolled, which
   removed the main way of making contact from everywhere except the one place
   nobody has decided to enquire yet.

   Because it no longer has a visible/hidden state, it needs no script at all -
   it is plain markup and CSS, and cannot fail to appear.                      */

/* The corner stack. Both buttons live in one fixed column so they can never
   overlap each other, and "back to top" simply leaves a gap above WhatsApp
   when it is not needed. */
.corner-actions {
    position: fixed;
    right: clamp(1rem, 2.5vw, 2rem);
    bottom: clamp(1rem, 2.5vw, 2rem);
    z-index: 90;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .625rem;
}

.wa-fab {
    display: grid;
    place-items: center;
    /* Comfortably above the 44px minimum touch target. */
    width: clamp(62px, 6.4vw, 70px);
    height: clamp(62px, 6.4vw, 70px);

    /* No background of its own. The button used to be a green disc with a white
       bubble on top of it; the logo is now drawn whole inside the SVG - green
       bubble, white keyline, white handset - so what the visitor sees is the
       WhatsApp mark itself rather than our approximation of it. That also means
       the tail of the bubble is visible instead of being swallowed by a circle. */
    border-radius: 50%;

    transition: opacity var(--transition), transform var(--transition),
                visibility var(--transition);
}

/* The logo fills the button; its own padded viewBox keeps the keyline off the
   edge. The shadow is a drop-shadow rather than a box-shadow so it follows the
   bubble and its tail instead of boxing the mark back into a circle. */
.wa-fab svg {
    width: 100%;
    height: 100%;
    filter: drop-shadow(0 8px 14px rgba(14, 14, 14, .38));
    transition: filter var(--transition);
}

.wa-fab:hover,
.wa-fab:focus-visible {
    transform: translateY(-3px) scale(1.04);
}

.wa-fab:hover svg,
.wa-fab:focus-visible svg {
    filter: drop-shadow(0 14px 22px rgba(14, 14, 14, .45));
}

/* ---- Back to top ----
   Sits above the WhatsApp button and is deliberately smaller and quieter than
   it: one is a way to get around the page, the other is how a visitor becomes
   a customer, and they should not compete. */

.to-top {
    display: grid;
    place-items: center;
    width: clamp(44px, 4.4vw, 48px);
    height: clamp(44px, 4.4vw, 48px);

    background: rgba(255, 255, 255, .9);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--line-strong);
    border-radius: 50%;
    color: var(--ink);
    cursor: pointer;
    box-shadow: 0 8px 20px -8px rgba(14, 14, 14, .38);

    transition: opacity var(--transition), transform var(--transition),
                visibility var(--transition), background-color var(--transition),
                color var(--transition), border-color var(--transition);
}

.to-top svg {
    width: 20px;
    height: 20px;
}

.to-top:hover {
    background: var(--ink);
    border-color: var(--ink);
    color: #fff;
    transform: translateY(-2px);
}

/* Hidden until the visitor is far enough down the page to want it. */
.to-top:not(.is-visible) {
    opacity: 0;
    visibility: hidden;
    transform: translateY(10px) scale(.9);
    pointer-events: none;
}

@media print {
    .corner-actions {
        display: none;
    }
}

/* ---- Service card ------------------------------------------------------- */

.service-card {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%; /* equal heights across the grid */
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    /* Clips the photograph and the hover rule to the rounded corner. */
    overflow: hidden;
    transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition);
}

.service-card:hover {
    border-color: var(--gold);
    transform: translateY(-4px);
    box-shadow: var(--shadow-lift);
}

.service-card__media {
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--ground-deep);
}

.service-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--transition-slow);
}

.service-card:hover .service-card__media img {
    transform: scale(1.05);
}

.service-card__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: clamp(1.5rem, 2.5vw, 2.25rem);
}

.service-card__number {
    font-family: var(--font-display);
    font-size: var(--fs-numeral);
    line-height: 1;
    color: var(--gold);
    margin-bottom: var(--space-md);
}

.service-card__title {
    font-size: var(--fs-h3);
    margin-bottom: var(--space-sm);
}

.service-card__text {
    color: var(--text-muted);
    font-size: .9375rem;
}

/* ---- Service card actions ----
   Pushed to the foot of the card by margin-top:auto, so the two actions line
   up across the whole grid however long each description runs. */

.service-card__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-md) var(--space-lg);
    margin-top: auto;
    padding-top: var(--space-lg);
}

.service-card__action {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    /* Keeps the tap target a full 44px without opening a gap in the layout. */
    padding-block: .625rem;
    background: none;
    border: 0;
    font-family: inherit;
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    text-decoration: none;
    color: var(--ink);
    cursor: pointer;
    transition: color var(--transition);
}

.service-card__action svg {
    width: 17px;
    height: 17px;
    transition: transform var(--transition);
}

.service-card__action:hover {
    color: var(--gold-deep);
}

.service-card__action:hover svg {
    transform: translateX(3px);
}

.service-card__action--whatsapp {
    color: var(--text-muted);
}

.service-card__action--whatsapp:hover {
    color: #1c8c47; /* WhatsApp green, darkened to stay readable on white */
}

/* Gold rule that draws itself along the bottom edge on hover. */
.service-card::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 2px;
    background: var(--gold);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transition-slow);
}

.service-card:hover::after {
    transform: scaleX(1);
}

/* The gallery is a slider - its slide and caption styles live in sections.css
   alongside the rest of the carousel. */

/* ---- Contact detail list ------------------------------------------------ */

.detail-list {
    display: grid;
    gap: var(--space-xl);
    margin: 0;
}

.detail__label {
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--gold-deep);
    margin-bottom: var(--space-2xs);
}

.detail__value {
    font-size: 1.0625rem;
    color: var(--text);
    text-decoration: none;
}

a.detail__value:hover {
    color: var(--gold-deep);
    text-decoration: underline;
}

.detail__value--muted {
    color: var(--text-muted);
}

/* The address block links through to Google Maps. */
.detail__value--address {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    font-size: 1rem;
    line-height: 1.55;
}

a.detail__value--address:hover {
    text-decoration: none;
}

a.detail__value--address:hover span:not(.detail__maps) {
    text-decoration: underline;
}

.detail__maps {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    margin-top: .5rem;
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--gold-deep);
}

.detail__maps svg {
    width: 14px;
    height: 14px;
    flex: none;
}

a.detail__value--address:hover .detail__maps {
    text-decoration: underline;
}

/* ---- Form --------------------------------------------------------------- */

.form-card {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: clamp(1.5rem, 3.5vw, 2.75rem);
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-lg);
}

.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    min-width: 0;
}

.field--full {
    grid-column: 1 / -1;
}

.field__label {
    display: flex;
    align-items: center;
    gap: .625rem;
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--text-muted);
}

/* Marks the fields that may be left blank. Saying so beside the label is
   friendlier than an asterisk on every other field, and it is only needed
   because every field but this one is required. */
.field__optional {
    font-size: .625rem;
    font-weight: 500;
    letter-spacing: .12em;
    color: #a49d94;
}

.field__control {
    width: 100%;
    min-height: 52px;
    padding: .875rem 1rem;
    background: var(--paper);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    font-size: 1rem;
    color: var(--text);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.field__control::placeholder {
    color: #a49d94;
}

.field__control:hover {
    border-color: var(--text-muted);
}

.field__control:focus {
    outline: none;
    border-color: var(--gold-deep);
    box-shadow: 0 0 0 3px rgba(138, 109, 40, .16);
}

textarea.field__control {
    min-height: 160px;
    resize: vertical;
    line-height: 1.6;
}

/* The service dropdown. The browser's own arrow is replaced with one drawn in
   the brand gold, because the native control is styled differently by every
   browser and the default is the one thing on the form that would look
   borrowed. The SVG is inlined as a data URI so it costs no extra request. */
.field__control--select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.75rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a6d28' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1rem center;
    background-size: 18px 18px;
    cursor: pointer;
}

/* Validation messages, written to be read rather than parsed. */
.field__error {
    display: block;
    font-size: .8125rem;
    line-height: 1.5;
    color: #a4342a;
}

.field__control.invalid,
.invalid .field__control {
    border-color: #a4342a;
}

/* Blazor adds .valid to every touched field; we only style the invalid ones. */
.field__control.valid {
    border-color: var(--line-strong);
}

/* The honeypot: off-screen, skipped by keyboard, invisible to people. */
.honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ---- Form status messages ----------------------------------------------- */

.form-status {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    padding: var(--space-lg);
    border-left: 3px solid var(--gold);
    background: var(--ground);
}

.form-status__title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    color: var(--ink);
}

.form-status__text {
    font-size: var(--fs-small);
    color: var(--text-muted);
    max-width: none;
}

.form-status--error {
    border-left-color: #a4342a;
}

.form-status--notice {
    border-left-color: var(--text-muted);
}

.form-status a {
    color: var(--gold-deep);
}

/* Small spinner shown inside the submit button while sending. */
.spinner {
    width: 16px;
    height: 16px;
    border: 2px solid rgba(14, 14, 14, .3);
    border-top-color: var(--ink);
    border-radius: 50%;
    animation: spin .7s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ---- Full-screen photograph viewer -------------------------------------
   Opened from the gallery. See Components/Shared/Lightbox.razor.
   The animations here are covered by the global prefers-reduced-motion block
   at the foot of sections.css, which reduces every duration to nothing.      */

.lightbox {
    position: fixed;
    inset: 0;
    /* Above the corner buttons (90), the header (100), the mobile panel (99)
       and the skip link (200) - but below the Blazor error banner (1000),
       which must always be reachable. */
    z-index: 300;

    display: grid;
    place-items: center;
    padding: clamp(1rem, 4vw, 3rem);

    background: rgba(10, 9, 7, .95);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    animation: lightbox-in 220ms cubic-bezier(.22, .61, .36, 1);
}

/* The overlay is focused by script so the keyboard reaches it; that focus is
   a mechanism, not something to draw a ring around. The controls inside keep
   their own focus rings. */
.lightbox:focus {
    outline: none;
}

@keyframes lightbox-in {
    from {
        opacity: 0;
    }
}

.lightbox__figure {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(.875rem, 2vw, 1.25rem);
    margin: 0;
    max-width: 100%;
    max-height: 100%;
}

.lightbox__image {
    /* Fills the space left after the padding and the caption, without ever
       cropping - a portfolio photograph is the whole point of the screen. */
    max-width: 100%;
    max-height: calc(100dvh - 11rem);
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--radius);
    box-shadow: 0 40px 80px -30px rgba(0, 0, 0, .9);
    animation: lightbox-image-in 320ms cubic-bezier(.22, .61, .36, 1);
}

@keyframes lightbox-image-in {
    from {
        opacity: 0;
        transform: scale(.985);
    }
}

.lightbox__caption {
    display: flex;
    align-items: baseline;
    justify-content: center;
    flex-wrap: wrap;
    gap: .875rem;
    text-align: center;
    color: #fff;
}

.lightbox__counter {
    font-family: var(--font-display);
    font-size: 1.125rem;
    line-height: 1;
    color: var(--gold-light);
}

.lightbox__label {
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
}

/* ---- Viewer controls ---- */

.lightbox__close,
.lightbox__nav {
    position: absolute;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition),
                border-color var(--transition);
}

.lightbox__close:hover,
.lightbox__nav:hover {
    background: #fff;
    border-color: #fff;
    color: var(--ink);
}

.lightbox__close svg,
.lightbox__nav svg {
    width: 21px;
    height: 21px;
}

.lightbox__close {
    top: clamp(.75rem, 2.5vw, 1.75rem);
    right: clamp(.75rem, 2.5vw, 1.75rem);
}

.lightbox__nav {
    top: 50%;
    translate: 0 -50%;
}

.lightbox__nav--prev {
    left: clamp(.5rem, 2.5vw, 1.75rem);
}

.lightbox__nav--next {
    right: clamp(.5rem, 2.5vw, 1.75rem);
}

/* On a phone the arrows would sit on top of the photograph, so they move to
   the bottom corners where a thumb reaches them anyway - and swiping works. */
@media (max-width: 640px) {
    .lightbox__nav {
        top: auto;
        bottom: 1rem;
        translate: none;
    }

    .lightbox__image {
        max-height: calc(100dvh - 13rem);
    }
}
