
.no-suggestions-placeholder {
    animation: suggestion-pulse 2s ease-in-out infinite;
}
@keyframes suggestion-pulse {
    0%, 100% { opacity: 0.6; }
    50% { opacity: 1; }
}

.card-subtitle {
    margin-bottom: 0.2rem;
    width: 100%;
    white-space: nowrap;
    flex-direction: row;
    display: flex;
    align-items: center;
}

.dialog .results .card .card-subtitle {
    margin-bottom: 0;
}

.card-list {
    width: 100%;
    flex-direction: column;
    /*justify-content: start;*/
    align-items: flex-start;
    padding: 0.6rem 0.6rem 14.4rem 0.6rem;
    gap: clamp(0px, 1vh, 0.9rem);
    background: none;
    height: calc(100vh - 94px); /* fits plan and broadcast */
    overflow-y: scroll;
    overflow-x: hidden;
    box-shadow: 0 0 0.3rem #000;
}

.dialog .card-list {
    padding: 0;
    height: inherit;
}

.dialog .stack {
    gap: 0.8rem;
}

.card-list-section {
    gap: 0.2rem;
    padding: 0;
    display: block;
}

.page.explore .content-panel{
    padding-bottom: 20vh;
    overflow-y: auto; /* Enable vertical scrolling */
    overflow-x: hidden;
}

.explore_edit.page > .content-panel {
    justify-content: space-between;
    padding: 1rem;
    align-items: flex-start;
    color: black;
    gap: 0.25rem !important;
}

.explore_edit.page .input-group {
    width: 100%;
}

/* Label-to-input spacing: more vertical space within, less between controls */
.explore_edit.page label .text {
    margin-bottom: 0.35rem;
}

.explore_edit.page .input-label {
    margin-bottom: 0.35rem;
    display: block;
}

.explore_edit.page > .content-panel > label,
.explore_edit.page > .content-panel > .input-group {
    margin-bottom: 0;
    padding: 0;
}

/* Related buttons inline with inputs */
.explore_edit.page .location-picker-container {
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
}

.explore_edit.page .location-picker-container .input-field {
    flex: 1;
}

.explore_edit.page .row {
    flex-direction: row;
    gap: 0.5rem;
    width: 100%;
}

.explore_edit.page .category-choices {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    gap: 4px !important;
}

.explore_edit.page .category-choices .choice {
    flex: 0 0 auto;
    width: auto !important;
}

.edit-actions-row {
    display: flex;
    flex-direction: row !important;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid #ddd;
}

.edit-actions-row .action-item.cancel {
    color: #666;
}

.edit-actions-row .action-item.cancel:hover {
    color: #333;
}

.page.timeline .card-list {
    /*padding-top: 50vh;*/
    /*padding-bottom: 50vh;*/
    gap: 0.3rem;
    align-items: end;
    justify-content: space-around;
}

.activity-list {
    width: 100%;
}

.activity-list .collapse .card-list {
    gap: 0;
}

.card-people {
    flex-direction: row;
    gap: 0.25rem;
}

.card select,
.card option {
    background-color: #0008;
    color: white;
    border: none;
}

.image {
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50% 50%;
}

.card.canceled {
    opacity: .6;
}

.can-cancel{
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    opacity: 1;
}

.delete-attachment {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
}

.card.canceled .can-cancel
.action-item.cancel
{
    display: none;
}

.card.canceled
.action-list {
    display: none;
}

.canceled-message {
    align-items: center;
    opacity: 1;
    font-size: 1.2rem;
}

.card {
    border-radius: 1.3rem;
    background-color: #FFF3;
    color: #ffffff;
    padding: 0;
    margin: 0;
    /*width: auto;*/
    /*width: calc(100% - 16px);*/
    width: 100%;
    align-self: center;
    user-select: none;
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50% 50%;
    text-shadow: 1px 1px 0 black;
    flex-direction: column;
    align-content: space-between;
    justify-content: space-between;
    height: auto;
    position: relative;
    /* transition: all 300ms ease-in-out; */
}

.dialog .card.settle,
.page.settle_split .card,
.page.settle .card {
    background: #dddddd;
    border-radius: 0.5rem;
    color: black;
    text-shadow: none;
    width: clamp(388px, 36dvh, 500px);
    height: auto;
    min-height: fit-content;
    padding: 1rem;
    gap: 1rem;
}
.dialog .card-list,
.page.settle_split .card-list,
.page.settle .card-list {
    flex-flow: wrap;
    justify-content: center;
}
.dialog .content-panel .person .text {
    font-size: 0.9rem;
}

.card-inner {
    padding: 1.5rem;
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50% 50%;
    border-radius: 1.3rem;
    /* transition: all 300ms ease-in-out; */
}

.smart .card-inner {
    background-color: grey;
}

.smart.early-morning .card-inner {
    background-color: darkred;
}

.smart.breakfast .card-inner {
    background-color: darkorange;
}

.smart.morning .card-inner {
    background-color: goldenrod;
}

.smart.lunch .card-inner {
    background-color: darkgreen;
}

.smart.afternoon .card-inner {
    background-color: darkslateblue;
}

.smart.dinner .card-inner {
    background-color: indigo;
}

.smart.evening .card-inner {
    background-color: darkviolet;
}

.smart.late-night .card-inner {
    background-color: black;
}

.card.smart .content-panel {
    border-radius: 0;
}

.smart .card-tags {
    white-space: normal;
    flex-direction: row;
    width: auto;
}

.smart .hash-tag.gold {
    padding: 0.25rem 0.5rem;
    border-radius: 1.2rem;
    background-color: white;
    color: black;
}

.card-tags {
    display: flex;
    flex-direction: row;
    justify-content: flex-start; /* Issue #2379: ensure tags stack from left */
    margin: 0 0;
    width: 100%;
    overflow-x: scroll;
    overflow-y: hidden;
    height: 1.5rem; /* changed to scale as the font height driven tags scale. */
    /* 2026-05-29 Pixel-7 audit: same fix as .choice-set — the last chip
       in this scroller used to hard-cut mid-word ("restaur…" for
       "restaurant") with no hint of more content. Fade the right edge
       so the clip reads as "scrollable" instead of "broken". */
    mask-image: linear-gradient(to right, black calc(100% - 1rem), transparent);
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 1rem), transparent);
}

.page.explore .hash-tag {
    font-size: 0.8rem;
    flex: 0 0 auto;
}

.page.explore .hash-tag.match,
.page.explore_detail .hash-tag.match,
.page.timeline .hash-tag.match {
    background-color: #2d8f4e;
}

.hash-tag.match::after {
    content: ' \2714';
}

/* TasteMatch tag match — secondary priority, muted yellow with checkmark */
.hash-tag.taste-match-tag {
    background-color: #d4b96a;
    color: white;
}
.hash-tag.taste-match-tag::after {
    content: ' \2714';
}

.page.explore .hash-tag.synonym-match,
.page.explore_detail .hash-tag.synonym-match,
.page.timeline .hash-tag.synonym-match {
    background-color: #b8860b;
}

.explore.page .action-item.book {
    font-size: 1rem;
}

.page.explore .card-people .circle .text {
    margin: 0 0 0 1px;
    padding-top: 1px;
    font-size: 0.7rem;
    white-space: nowrap;
}

.page.explore .card.collapsed .card-tags,
.page.explore .card.collapsed .card-people,
.page.explore .card.collapsed .content-panel {
    display: none;
}

.page.explore .card .action-list .icon {
    width: 1rem;
    height: 1rem;
    /* transition: width 300ms ease-in-out, height 300ms ease-in-out; */
}

.page.explore .card .background.image {
    opacity: 0.50;
}

.page.explore .card.collapsed .background.image {
    opacity: 0.20;
}

.page.explore .card.collapsed {
    min-height: 92px;
}

.page.explore .card-list > .card-title {
    margin-bottom: 1rem;
    flex-direction: column;
}

.page .card-list > .card-title {
    display: none;
}

.page.explore .card-list > .card-title {
    display: flex;
}

.page.explore .card-list > .card-title .card-title {
    font-weight: bolder;
    font-size: 11px;
}

.card .content-panel {
    background-color: #0006;
}

.page.explore .card.explore .icon {
    position: static;
    margin: 0;
}

/* Fallback for cards without images */
.card.no-image {
    min-height: 140px;
}
.card.no-image .card-title {
    font-size: 1.1rem;
}

.card .titles .row .col {
    margin-left: 1.2rem;
}

.page.explore .action-list .text {
    /*display: none;*/
}

.page.explore .card.explore .card-title {
    font-size: 1rem;
    background: linear-gradient(90deg, #dddddddd, #cccccccc);
    border-radius: 0.25rem;
    padding: 0.25rem;
    justify-content: center;
    text-shadow: none;
    color: black;
}

.page.explore .card.explore .sub-title {
    font-size: clamp(6px, min(1.05dvw, 1.05dvh), 2.4rem);
}

.page.explore .card.explore .row {
    justify-content: space-between;
}

.page.explore .card.explore .content-panel .action-item {
    padding: 0;
}

.dialog .card,
.page .card {
    /*min-height: 60px;*/
    /*background-size: 72%;*/
    box-shadow: 2px 2px 4px 1px #00000088;
    width: 100%;
    padding: 0.6rem;
    /* min-height: 100%; BREAKS TIMELINE */
}

.page .message-panel .card{
    width: calc(100% - 12px);
    height: min(100vw, 75vh);
    min-height: min(100vw, 75vh);
    max-height: min(100vw, 75vh);
}

.page .attachments .card{
    /*width: min-content;*/
}

.card-inner {
    margin-left: 0.3rem;
    color:#000000;
}

.page.timeline .card {
    padding: 0;
    /* 2026-05-22 (Greg PM note): pre-fix was margin:0.6rem auto 0 — top
       gap only, no bottom — so adjacent timeline period cards sat
       flush against each other with no visual separator. Greg's
       screenshot showed the Breakfast period's tag row touching the
       Morning period's header with no border between them. Symmetric
       top+bottom margin produces a 1.2rem total gap between periods.
       Also added a thin border-bottom to the period container so the
       boundary is explicit even when both periods scroll into view.   */
    margin: 0.6rem auto;
    width: 98%;
    border-left: 0.9rem solid #0004;
    border-bottom: 1px solid #8883;
    /* 2026-05-20 (Greg PM note): pre-fix was border-radius:0 which
       made the OUTER period container rectangular while the inner
       suggestion cards (border-radius:15px) were rounded — visually
       inconsistent. .suggestion-card / .card.activity have their own
       higher-specificity border-radius rules so they're unaffected. */
    border-radius: 0.9rem;
    background: none;
    box-shadow: none;
    /* transition: none; */

}

.page.timeline .activity.card {
    border-left: none;
    padding: 1em;
}

.page.explore_detail .card {
    min-height: 77vh;
}

.page.explore_detail .card .action-item.open {
    display: none;
}

.page.collect .card {
    /* background-blend-mode: darken; */
    /*filter: brightness(50%);*/
}

.page.collect .card .background.image {
    display: none;
}

.page.explore .card {
    min-height: 44vh;
    /* transition: opacity 200ms ease-in-out, min-height 200ms ease-in-out; */
    padding: 0.6rem;
    width: 100%;
}

.page.collect .card {
    background-color: #0005;
    padding: 1.2rem;
}

/*.card .card-inner > * {*/
/*    z-index: 200;*/
/*}*/

.card .background {
    position: absolute;
    left: 0;
    right: 0;
    opacity: 0.85;
    z-index: 100;
}

.card .background.top {
    top: 0;
}

.card .background.bottom {
    bottom: 0;
}

.card .amount {
    height: min-content;
    background: white;
    padding: 0.5em;
    border-radius: 1em;
    font-size: 0.9rem;
    text-align: center;
}

.page.settle_day .card .amount {
    padding: 0;
}

.page.settle_split .card .turn > .amount,
.page.settle_split .card .turn > .rack > .amount {
    /* padding: 0; */
    color: whitesmoke;
    background-color: dimgray;
    font-weight: bold;
}

.page.settle_day .card {
    text-shadow: none;
}

.card .titles .amount {
    justify-content: center;
    align-content: center;
    justify-items: center;
    align-self: center;
}

.docs,
.bulletin {
    background: cornflowerblue;
    padding: 1em;
    border-radius: 1em;
    color: white;
    font-size: 1.3rem;
    justify-self: center;
    text-align: center;
    width: calc(100% - 2em);
    margin: 1em;
}

.docs {
    font-size: 0.9rem;
    color: #321;
    justify-self: flex-start;
    text-align: left;
    background: lightgoldenrodyellow;
}

.docs p {
    margin: 1em 0 0 -0.5em;
}

.settle.page > .content-panel .title {
    font-size: 2em;
    padding: 0;
}

.card-section {
    display: flex;
    flex: initial;
    flex-direction: column;
    align-content: center;
    justify-content: right;
    gap: 0.9rem; /* added for settle */
    overflow-y: visible; /* let content flow — outer card-list handles scrolling */
    overflow-x: visible;
}

.card-quadrant {
    display: flex;
    flex-direction: column;
    align-content: space-between;
    justify-content: space-between;
    gap: 0.5rem;
}

.card.connect .card-quadrant {
    flex-direction: row;
    justify-content: space-evenly;
}

.card.connect .card-quadrant .action-list {
    width: auto;
    flex-direction: column;
    justify-content: center;
}

.card-subtitle {
    font-size: 0.8rem;
    flex-direction: row;
    align-items: flex-start;
    display: flex;
    align-content: space-around;
    justify-content: space-between;
    width: 100%;
}

.card-text {
    font-size: 10pt;
    background-color: rgba(0, 0, 0, 0.5);
    width: 100%;
    border-radius: 0.25em;
    padding: 0.25em 0.125em;
    margin: 0.25em 0;
}

.card-you {
    font-size: 10pt;
    background-color: rgba(0, 0, 0, 0.5);
    padding: 0.5em;
    width: 100%;
    text-align: right;
}

.card-title {
    font-size: 1.2rem;
    flex-direction: row;
    align-items: flex-start;
    display: flex;
    align-content: space-around;
    justify-content: space-between;
    width: 100%;
}

.page.collect_board .card-title {
    align-content: center;
    justify-content: flex-start;
    align-items: center;
}

.card-title-text {
    padding: 0.3rem 0.6rem;
    border-radius: 0.33rem;
    font-size: 1em;
    display: inline-flex;
    flex-direction: row;
    justify-content: center;
    vertical-align: middle;
    margin-right: 1em;
}

.card.explore {
    background-color: #ff6666;
    box-shadow: 2px 2px 4px 1px #00000088;
}

.card.connect {
    background-color: #e99821;
    padding: 1rem;
}

/* .page.explore .row > * {
    align-self: auto;
} */

.page.explore > .content-panel > .row {
    width: 100%;
    gap: 0.25em;
    /*padding: 0;*/
}

.page.explore .card-list {
    padding: 3px 3px 50vh 3px;
    width: 100%;
}

.page.explore .card.explore {
    background-color: #ff6666;
    box-shadow: 2px 2px 4px 1px #00000088;
    width: 47vw;
    margin: 0 3px 3px 0;
    background-size: auto;
}

/*.page.explore .card.explore:nth-child(odd) {*/
/*    align-self: flex-start;*/
/*}*/
/*.page.explore .card.explore:nth-child(even) {*/
/*    align-self: flex-end;*/
/*}*/

.page.explore .card .card-inner > .row,
.page.explore .card .card-inner > .row .col .row,
.page.explore .card .card-inner > .row .col .row .col {
    /*width: 100%;*/
    /*margin: 0 auto;*/
}

.page.explore .row .icon-frame {
    align-self: center;
}

.card {
    background: linear-gradient(rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.35)), black center/cover no-repeat;
    /* prevents the exported black frames from figma from showing. */
    /* 10% overall darkening: 0.1 base tint + extra 0.25 at edges for readability */
    background-size: 103%;
    gap: 0;
}

.card.split {
    gap: 0.9rem;
}

.card-inner {
    box-shadow: 0vw 0vw .5vw rgba(0, 0, 0, 0.7);
    /* background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0), rgba(0, 0, 0, 0), rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.7)), black center/cover no-repeat; */
    /* background-size: 103%; */
    gap: 0;
}

.card.collect,
.card.board {
    background-color: #5667bc;
}

.card.plan {
    background-color: #67bc67;
}

.card.settle {
    background-color: #5623dE;
}

.card.settle .titles {
    width: 100%;
}

.card.settle .title {
    text-align: right;
    width: max-content;
    align-self: flex-end;
    justify-self: flex-end;
    color: white;
    border: 0 solid white;
    box-shadow: none;
}

.card.settle .content-panel > .title {
    background: none;
}

.card.settle .card-title {
    font-size: 15pt;
}

/*.card.settle .content-panel,*/
/*.card.settle .content-panel .text,*/
/*.settle .title .col .row,*/
/*.settle.page .card.settle .content-panel>.row {*/
/*    text-align: center;*/
/*    align-self: center;*/
/*    justify-self: center;*/
/*    justify-content: center;*/
/*    justify-items: center;*/
/*    padding: 0;*/
/*}*/

.settle-who .who,
.settle-who .amount,
.settle-who {
    text-align: center;
    align-self: center;
    justify-self: center;
}

.title .amount {
    margin: auto;
    text-align: center;
}

.settle-who .amount {
    font-size: 0.9rem;
}

.settle-who .who {
    font-size: 0.8rem;
}

.card-list .title .row .col {
    align-items: center;
    align-content: center;
    margin: 0 auto;
    justify-content: center;
    align-self: center;
    justify-self: center;
}

.green {
    color: #339966;
}

.red {
    color: #993333;
}

.black {
    color: #333333;
}

.dashboard-item .title,
.dashboard-item .text,
.dashboard-item .action-item {
    text-align: center;
    justify-self: center;
    justify-content: center;
    align-self: center;
    align-content: center;
}

.card.settle .action-item {
    align-self: flex-start;
}

.person .icon-frame {
    padding: 1.5px;
}

.person .icon {
    border-radius: 50%;
}

.titles .row .action-item .icon-frame {
    padding: 0.4rem;
}

.settle-who {
    margin: 0;
    background-color: #ffffffaa;
    font-size: 1em;
    padding: 1rem;
    border-radius: 0.5em;
}

.card-list .card-list .row {
    width: 100%;
}

.card-list > .card {
    width: 100%;
    height: clamp(200px, auto, 300px);
    /*min-height: clamp(200px, 33vh, 300px);*/
    white-space: break-spaces;
    /* transition: opacity 300ms ease-in-out, padding 300ms ease-in-out, max-height 300ms ease-in-out, max-height 300ms ease-in-out, min-height 300ms ease-in-out, minwidth 300ms ease-in-out; */
}

/*.action-item.person .text,*/
.message-item .text,
.person .text {
    /* transition: all 300ms ease-in-out; */
    padding-right: 1rem;
}

.message-item:hover .text,
.person:hover .text {
    /* transition: all 300ms ease-in-out; */
}
.div.text,
.page.explore .action-item .text {
    /*display: none;*/
}
.page.explore .action-item:hover .text {
    display: flex;
    /*position: absolute;*/
    /*background-color: black;*/
    /*z-index: 999;*/
    /*margin-right:2em;*/
    /*bottom:0;*/
}

.person text {
    /*display: none;*/
}
.person:hover text {
    display: flex;
    position: absolute;
    background-color: black;
    z-index: 99999;
    margin-right: 2em;
    bottom: 0;
}

.page.explore .action-item.collapse:hover .text {
    display: none;
}

.person-icon:hover .text {
    display: block;
    background: #0008;
    position: absolute;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    border-radius: 1rem;
    z-index: 99999;
    top: -66%;
    opacity: 1;
    visibility: visible;
    /* transition: all 1300ms ease-in-out; */
}

.activity-list .collapse .card {
    opacity: 0;
    min-height: 0;
    max-height: 0;
    margin: 0;
    padding: 0;
    /* transition: opacity 300ms ease-in-out, padding 300ms ease-in-out, max-height 300ms ease-in-out, max-height 300ms ease-in-out, min-height 300ms ease-in-out, minwidth 300ms ease-in-out; */
}

.activity-list .collapse .card > * {
    display: none;
}

.activity-list > .row > .row > .action-item {
    background-color: transparent;
}

.activity-list > .row {
    border-top: 1px solid #bbb;
    padding: 1px;
}

.activity-list .row > .title {
    font-size: 1.6rem;
    background: none;
}

.activity-list > .row > .action-item .icon {
    transform: rotate(90deg);
    /* transition: transform 300ms ease-in-out; */
}

.activity-list > .row.collapse > .action-item .icon {
    transform: rotate(0deg);
    /* transition: transform 300ms ease-in-out; */
}

.activity-list > .card-list {
    padding-bottom: 1em;
    height: auto;
}

.activity-list > .card-list.collapse {
    gap: 0;
    padding-bottom: 0;
}

.page.explore .card.explore .content-panel .action-item.favorite .text {
    display: block;
}

.page.explore .action-item.favorite .text {
    display: block;
}

.section-title {
    margin: 0 -0.125em;
    flex-direction: row;
    background: none;
    width: 100%;
    padding: 0.125rem;
    gap: 0.125rem;
    justify-content: space-between;
    align-content: space-between;
}

.titles {
    flex-direction: row;
    justify-content: flex-start;
    gap: 0.1rem;
}

.card.contact {
    background: #dddddd;
}

.card.contact > .row {
    justify-content: space-between;
}

.card.contact > .row > select {
    padding: 1rem;
    border-radius: 1rem;
}

.card.contact .card-tags {
    width: 100%;
}

.card.connect .titles .col {
    align-items: end;
}

.expense-list {
    width: 100%;
    gap: 0.5rem;
    height: 172px;
    overflow-y: scroll;
    padding: 0.5rem;
    background: rgba(0, 0, 0, 0.05);
    box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.2);
    border-radius: 0.9rem;
}

.page.settle_split .card.expense-item,
.page.settle .card.expense-item {
    color: black;
    background: rgba(255, 255, 255, 0.75) none;
    padding: 0.5rem 0;
    border-radius: 0.5em;
    gap: 0.5rem;
}

.expense-item .text {

}

.page > .content-panel .card.expense-item .title {
    padding: 0;
}

.card.expense-item .split-amounts .rack {
    padding: 0;
}

.card.expense-item > .rack {
    padding: 0 2em;
    justify-content: space-between;
}

.page.collect_board .card .action-item.collect {
    display: none;
}

.page.timeline .card.activity {
    width: 100%;
    border-radius: 0.25em;
    margin: 0 0.36rem 0.25rem auto;
    height: auto;
}

.page.timeline .card-inner .spaced {
    color: fuchsia;
    margin-bottom: 1rem;
}

.page.timeline .card-actions.spread {
    flex-direction: column;
    align-items: flex-start;
}

.page.timeline .card .suggestion-card {
    width: auto;
    max-width: 47vw;
    background-color: #ef5656 !important;
    border-radius: 15px;
    margin: 1vw;
    height: fit-content;
    min-height: 7rem;
    min-width: 16rem;
}
.cato-suggestion .suggestion-card {
    border-left: 2vw solid goldenrod !important;
    border-radius: 15px;
}

/* "estimated" prefix for hours_source='ai_estimated' (Greg PM
 * 2026-05-22). Muted/italic so it reads as a qualifier on the
 * Hours: label, not the headline. */
.hours-estimated-prefix {
    font-style: italic;
    font-weight: 400;
    color: #aaa;
    text-transform: lowercase;
    letter-spacing: 0;
}

.source-badge {
    position: absolute;
    /* 2026-05-29 QA: badge moved from top-right (top:0.3rem right:0.3rem)
       to top-left BELOW the compass open-icon. Previous top-right
       placement overlapped the tag-row chip on narrow cards once the
       card-section padding pushed chips up against the corner. The
       compass .icon-frame is ~2rem tall + a sliver of top padding,
       so starting at 2.4rem clears it. All sizes in rem so the
       layout scales with the SPA's dynamic base font-size (mobile
       ≈11.7px → desktop ≈20px). */
    top: 2.4rem;
    left: 0.4rem;
    right: auto;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.15rem;
    padding: 0.15rem 0.4rem;
    border-radius: 0.7rem;
    font-size: 0.55rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05rem;
    z-index: 2;
    opacity: 0.85;
    backdrop-filter: blur(4px);
}
.source-badge svg { flex-shrink: 0; }
.source-cato { background: rgba(218, 165, 32, 0.9); color: white; }
.source-nearby { background: rgba(22, 160, 133, 0.9); color: white; }
.source-database { background: rgba(41, 128, 185, 0.9); color: white; }
/* No tag-row padding override needed now — badge sits in the upper-
 * left card-art area, not next to the tag row. */

.suggestion-card .card-section .titles .col .card-title {
    padding: 1vw;
    margin-top: 1vw !important;
}

.suggestion-card .card-section .titles .col {
    overflow-x: hidden;
}

.suggestion-card .card-section {
    padding: 1vw;
    color: #ffffff;
    text-shadow: 1px 1px 2px rgba(0,0,0,0.6);
}

.suggestion-card .card-inner {
    color: #ffffff;
}

.suggestion-card .card-tags {
    display: flex;
    flex-wrap: nowrap;
    gap: 2px;
    padding: 2px 4px;
    overflow-x: auto;
    overflow-y: hidden;
    max-width: 100%;
    width: 100%;
    box-sizing: border-box;
}

.suggestion-card .card-tags .hash-tag {
    font-size: 0.65rem;
    padding: 1px 5px;
}

.suggestions {
    flex-direction: row;
    overflow-x: scroll;
    overflow-y: hidden; /* prevent vertical scroll trap — only horizontal scroll */
    min-height: max(110px, 13vh); /* hold space during card swap to prevent layout collapse */
    gap: 0.5rem; /* 2026-05-20: prevent edge-to-edge cards visually overlapping on narrow viewports */
}

/* 2026-05-19 (ui-ux/2026-05-19): disclosure triangle to expand a period's
   .suggestions row from horizontal-scroll into a wrapping grid. The button
   lives in the title row of card_timeline.js; the rotate + layout-flip
   both key off the `.expanded` class added by togglePeriodExpand(). */
.card.timeline .disclosure-triangle {
    display: flex !important;
    flex-direction: row !important;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    cursor: pointer;
    color: #555;
    padding: 0;
    margin-right: 0.25rem;
    border-radius: 0.25rem;
    transition: transform 0.18s ease, background-color 0.15s ease;
    flex-shrink: 0;
    user-select: none;
}
.card.timeline .disclosure-triangle:hover {
    background-color: rgba(0, 0, 0, 0.06);
}
.card.timeline.expanded .disclosure-triangle {
    transform: rotate(90deg);
}

/* When expanded: .suggestions becomes a wrapping grid with unlimited height.
   Cards keep their min/max widths (defined a few rules down) so wrapping
   produces clean rows automatically. */
.card.timeline.expanded .suggestions {
    flex-wrap: wrap !important;
    overflow-x: visible !important;
    overflow-y: visible !important;
    max-height: none !important;
    height: auto !important;
    align-content: flex-start;
}
.card.timeline.expanded .suggestions .card.explore {
    /* Allow the natural max-width to govern; the wrap layout fills rows. */
    margin: 0.25rem;
}

/* 2026-05-19 (ui-ux/period-card-polish): period title was 1.2rem from the
   generic .card-title rule, which felt visually heavy relative to the
   disclosure-triangle + icon-frame next to it. Tighten just for the
   timeline period header — leaves other card titles (Explore, etc.)
   unchanged. */
.card.timeline .card-title {
    font-size: 1.0rem;
    line-height: 1.25;
}

/* R2 perf experiment 2026-05-19: contain layout/style so per-card SSE
   updates don't invalidate the whole document tree. Each period card
   becomes a layout/style containment root. */
.card.timeline {
    contain: layout style;
    /* 2026-05-20 (Greg PM note): period card outer container had square
       corners. Suggestion cards inside had border-radius:15px so they
       looked rounded, but the OUTER box framing each period (Breakfast,
       Lunch, etc.) was rectangular — visually inconsistent against the
       rounded suggestion cards inside. Match the suggestion-card radius
       and clip overflow so the inner left-edge color stripe rounds with
       the corners. */
    border-radius: 0.9rem;
    overflow: hidden;
}

/* R3 perf experiment 2026-05-19: defer rendering for off-screen suggestion
   cards (replaces "loading=lazy" since these use background-image, not <img>).
   content-visibility: auto skips paint/style for offscreen .card.explore,
   contain-intrinsic-size avoids scrollbar jitter while the browser estimates. */
.card.explore {
    content-visibility: auto;
    /* responsive: rem-based intrinsic so the placeholder size scales with
       the project's dynamic base font-size, matching the actual card
       widths set below.
       2026-05-20: height was 23rem (~276 px on mobile) but collapsed-
       state cards naturally render at ~120 px (10rem) — title + 2-line
       subtitle + tags-strip. The 23rem placeholder forced the
       .suggestions row to claim max(visible, 23rem) = 23rem height
       because offscreen cards in the horizontal scroller used the
       placeholder, leaving ~150 px of empty space below the visible
       cards. Use `auto` keyword so the browser remembers actual sizes
       after first paint; fallback is 10rem which closely matches the
       collapsed card's natural height. Expanded-state cards override
       with their own width/height rules at lines 1284-1294. */
    contain-intrinsic-size: auto 17rem auto 10rem;
}

/* 2026-05-20 (ui-ux/timeline-card-cleanup):
   COLLAPSED (default) state — pin timeline suggestion cards to the
   compact 170-200 px range. Without this override, the legacy rule
   `.page.timeline .card .suggestion-card { min-width: 16rem; max-width: 47vw }`
   (lines ~1101 above) kicks in once styleSuggestionCards() adds the
   .suggestion-card class late, blowing the cards out to 256-481 px
   depending on viewport. Higher specificity (id + 3 classes) ensures
   this rule wins over the .suggestion-card rule. */
#page-timeline .card.timeline:not(.expanded) .suggestions .card.explore,
#page-timeline .card.timeline:not(.expanded) .suggestions .card.explore.suggestion-card,
#page-timeline .card.timeline:not(.expanded) .suggestions .suggestion-wrapper {
    /* 2026-05-29 QA: shrunk ~15% (14→12rem min, 17→14.5rem max) so
       more cards fit in the horizontal scroller. Old range felt too
       large on Greg's Pixel 7 — only 1.3 cards visible per row.
       responsive: rem scales with the project's dynamic base font-size
       (mobile ≈ 11.7 px → ~140 px / desktop ≈ 20 px → ~240 px). */
    min-width: 12rem !important;
    max-width: 14.5rem !important;
    width: auto !important;
    /* 2026-05-20: without flex-shrink:0 the row's overflow-x:scroll fights
       with the min-width override and adjacent cards visually clip into
       each other on narrow (~400 px) viewports. The .expanded rule below
       already has this; matching it for collapsed. */
    flex-shrink: 0 !important;
}

/* 2026-05-20: in collapsed-state suggestion cards, .card-subtitle's
   default flex-direction:row (from .card-subtitle:639) crams the
   location row + rating-row side-by-side. On narrow cards (~150 px
   subtitle) the location SPAN's nowrap intrinsic width overflows its
   parent's overflow:hidden box symmetrically — clipping the leading
   "R" and trailing "y" of "Reno, NV - 2.5 Away" into "eno - 2.5 Awa".

   Pure-ellipsis fix attempted first (flex:1 1 0 + min-width:0 on SPAN,
   overflow:hidden on parent). It works on paper but the triple-flex
   chain (subtitle → innerFlex → SPAN+menu) plus the rating DIV sibling
   creates fragile sizing — the SPAN intermittently collapses to 0 px
   when innerFlex+ellipsis combine with the menu's flex-shrink:0.

   Pragmatic fix: stack the two subtitle children vertically (same as
   the .expanded rule at line 1361). Card is one line taller but all
   info stays visible, and the layout is stable across viewports.
   Defensive ellipsis still applied to the location SPAN in card.js
   for the rare case of an unusually long single-line location. */
#page-timeline .card.timeline:not(.expanded) .suggestions .card.explore .card-subtitle {
    flex-direction: column;
    align-items: stretch;
}

/* EXPANDED state (after disclosure-triangle click) — full-width column. */
.card.timeline.expanded .suggestions {
    flex-direction: column !important;
    flex-wrap: wrap !important;
    overflow-x: visible !important;
    overflow-y: visible !important;
    gap: 0.5rem;
    padding: 0.25rem 0;
}
#page-timeline .card.timeline.expanded .suggestions .card.explore,
#page-timeline .card.timeline.expanded .suggestions .card.explore.suggestion-card,
#page-timeline .card.timeline.expanded .suggestions .suggestion-wrapper {
    min-height: max(10rem, 14vh);
    width: 100% !important;
    min-width: 100% !important;
    max-width: 100% !important;
    flex-shrink: 0;
    border-radius: 0.75rem;
    overflow: hidden;
    margin: 0.25rem 0;
    position: relative;  /* anchor for the absolute-positioned corner dates */
}

/* ============================================================
   2026-05-20 PM notes A/B/C/D — Greg's card preview layout
   ALL gated to .card.timeline.expanded — collapsed/compact mode
   keeps its original layout unchanged.
   ============================================================ */

/* (A) Corner date labels in EXPANDED mode only.
   COLLAPSED — hide both labels (compact card has no room for two corner
   chips above a 170 px-wide title). The data still ships in the DOM so
   the inline-state hide is reversible.
   EXPANDED — absolutely position Added top-left, Updated top-right. */
#page-timeline .card.timeline:not(.expanded) .suggestions .card.explore .card-date-added,
#page-timeline .card.timeline:not(.expanded) .suggestions .card.explore .card-date-updated {
    display: none !important;
}
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-date-added,
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-date-updated {
    position: absolute;
    top: 0.35rem;
    font-size: 0.65rem;
    font-weight: 500;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    padding: 0.1rem 0.45rem;
    border-radius: 0.65rem;
    z-index: 3;
    white-space: nowrap;
    pointer-events: none;
    text-shadow: none;
}
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-date-added    { left:  0.4rem; }
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-date-updated  { right: 0.4rem; }

/* 2026-05-21 (Greg-B): in expanded state the CATO sparkle badge
   (.source-badge.source-cato, default top:4px right:4px) overlapped
   the "Updated [date]" badge — same corner, date won via higher
   z-index. Greg's suggestion: center the cato symbol between Added
   (top-left) and Updated (top-right). Position source-badge at
   top-center in expanded; collapsed state keeps default top-right
   (date labels are hidden there so no collision). */
#page-timeline .card.timeline.expanded .suggestions .card.explore .source-badge {
    /* 2026-05-29 QA: was top-center to dodge the date corners; now
       sits just under the compass open-icon on the left, matching
       the collapsed-state placement. Date corners aren't large
       enough to overlap once badge starts below the icon row. */
    left: 0.4rem;
    right: auto;
    transform: none;
    top: 2.0rem;
    z-index: 4;
}

/* Push the rest of the card content below the corner labels so they don't
   overlap the title in expanded mode. */
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-section {
    padding-top: 1.6rem;
}

/* (C) Sticky title — the chip row inside the card scrolls horizontally
   (card.css:1159 .suggestion-card .card-tags overflow-x:auto). Pin the
   title row to the left edge so users always see the activity name
   regardless of chip-row scroll position. */
#page-timeline .card.timeline.expanded .suggestions .card.explore .titles {
    position: sticky;
    left: 0;
    z-index: 2;
}

/* (D) Centered + action between title line and distance line.
   Targets the suggestion-menu-container's plus / add button. The existing
   markup puts the menu-container right-aligned next to the location text;
   in expanded mode we re-flow it to a centered row below the title. */
#page-timeline .card.timeline.expanded .suggestions .card.explore .titles .col {
    align-items: stretch;
    width: 100%;
}
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-subtitle {
    flex-direction: column;
    align-items: center;
}
#page-timeline .card.timeline.expanded .suggestions .card.explore .card-subtitle > div:first-child {
    flex-direction: column-reverse;  /* puts the menu-container ABOVE the text row */
    align-items: center !important;
    gap: 0.35rem;
    text-align: center;
}
#page-timeline .card.timeline.expanded .suggestions .card.explore .suggestion-menu-container {
    margin-left: 0 !important;
    margin: 0 auto !important;
}

/* 2026-05-14: the .suggestions row is the primary horizontal scroller, and
   each recommendation card's .card-tags row is the ONLY scroller permitted
   inside a card. Every other descendant clips — a nested overflow:auto/scroll
   here competes with the row scroll and traps touch gestures (continues the
   2026-04-16 scroll-trap cleanup). .suggestion-menu-container is excluded so
   its position:absolute dropdown isn't re-clipped at a tighter boundary than
   the card already imposes.
   2026-05-15 fix-up: also exclude .hash-tag chips. On a flex item,
   overflow != visible flips min-width:auto -> 0, which let chips SHRINK to
   fit instead of overflowing the row — so the row had nothing to scroll
   over and tags looked compressed. Excluding .hash-tag (and pinning
   flex-shrink:0 on chips below) keeps chip natural width so the row
   actually overflows and scrolls. */
.suggestions .card.explore *:not(.card-tags):not(.suggestion-menu-container):not(.hash-tag) {
    overflow: hidden;
}
.suggestions .card.explore .card-tags {
    overflow-x: auto;
    overflow-y: hidden;
}
.suggestions .card.explore .card-tags .hash-tag {
    flex-shrink: 0;          /* don't compress chips; force the row to overflow */
}

.icon.suggestion {
    height: 1rem;
}

.explore-card-description {
    max-height: 7vh;
    overflow-y: hidden; /* clip long descriptions — no scroll trap */
}

@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.4; transform: scale(1.3); }
}

.explore-card-category {
    font-size: 0.7rem;
    color: #ffffffaa;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-top: 0.25rem;
}

.explore-card-website {
    margin-top: 0.5rem;
    font-size: 0.85rem;
}

.explore-card-website a {
    color: #7ec8e3;
    text-decoration: none;
    word-break: break-all;
}

.explore-card-website a:hover {
    text-decoration: underline;
    color: #aee0f5;
}

.explore-card-website a::before {
    content: "\1F517\00a0";
}

.category-badge {
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.15rem 0.6rem;
    border-radius: 1rem;
    background-color: #e99821;
    color: #fff;
    margin: 0.25rem 0;
    text-shadow: none;
    width: fit-content;
}

.tag-editor-container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.3rem;
    padding: 0.4rem;
    min-height: 2rem;
    background: rgba(255,255,255,0.1);
    border-radius: 0.5rem;
    margin-bottom: 0.3rem;
}

.tag-editable {
    cursor: default;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    width: fit-content !important;
}

.tag-remove {
    cursor: pointer;
    font-size: 1.1em;
    font-weight: bold;
    opacity: 0.7;
    margin-left: 0.2rem;
}

.tag-remove:hover {
    opacity: 1;
    color: #ff4444;
}

.tag-add-row {
    display: flex;
    flex-direction: row;
    gap: 0.4rem;
    margin-top: 0.2rem;
    align-items: center;
}

.tag-add-row .input-field {
    flex: 1;
}

.tag-add-button {
    padding: 0.3rem 0.8rem;
    border: none;
    border-radius: 0.4rem;
    background: #2d8f4e;
    color: white;
    cursor: pointer;
    font-size: 0.85rem;
}

.tag-add-button:hover {
    background: #247a40;
}

/* ------------------------------------------------------------
 * 2026-05-24 (Greg report): Plan cards (and any future
 * floating list-card whose JS renders <div class="card X-card"
 * style="background:#fff;...">) inherit the global .card rule's
 * color:#ffffff + text-shadow:1px 1px 0 black — designed for
 * image / dark-gradient backgrounds. On their inline-white
 * background that read as ghostly text with poor contrast.
 *
 * Plan cards are list items (like .invitation-card already
 * is — see main.css ~1296), not image cards. Override to dark
 * text + no shadow. Same defensive override applied to
 * .plan-card-title / .plan-card-when so child selectors don't
 * pick up the inherited white.
 * ------------------------------------------------------------ */
.plan-card,
.plan-card .plan-card-header,
.plan-card .plan-card-title,
.plan-card .plan-card-when,
.plan-card .plan-responses,
.plan-card .plan-response-row {
    color: #1f2937;
    text-shadow: none;
}
.plan-card .plan-card-when {
    /* matches the inline color:#666 the JS sets; here only so the
     * cascade doesn't have to depend on inline-style winning. */
    color: #666;
}
