diff --git a/libraries/expo-iap/ios/ExpoIapModule.swift b/libraries/expo-iap/ios/ExpoIapModule.swift
index 3c803104..c220f614 100644
--- a/libraries/expo-iap/ios/ExpoIapModule.swift
+++ b/libraries/expo-iap/ios/ExpoIapModule.swift
@@ -148,6 +148,14 @@ public final class ExpoIapModule: Module {
return sanitized
}
+ AsyncFunction("getAllTransactionsIOS") { () async throws -> [[String: Any]] in
+ ExpoIapLog.payload("getAllTransactionsIOS", payload: nil)
+ let all = try await OpenIapModule.shared.getAllTransactionsIOS()
+ let sanitized = all.map { ExpoIapHelper.sanitizeDictionary(OpenIapSerialization.encode($0)) }
+ ExpoIapLog.result("getAllTransactionsIOS", value: sanitized)
+ return sanitized
+ }
+
AsyncFunction("clearTransactionIOS") { () async throws -> Bool in
ExpoIapLog.payload("clearTransactionIOS", payload: nil)
let success = try await OpenIapModule.shared.clearTransactionIOS()
diff --git a/libraries/expo-iap/src/modules/ios.ts b/libraries/expo-iap/src/modules/ios.ts
index eb8acb53..55a30cc8 100644
--- a/libraries/expo-iap/src/modules/ios.ts
+++ b/libraries/expo-iap/src/modules/ios.ts
@@ -357,6 +357,13 @@ export const getPendingTransactionsIOS: QueryField<
return (transactions ?? []) as PurchaseIOS[];
};
+export const getAllTransactionsIOS: QueryField<
+ 'getAllTransactionsIOS'
+> = async () => {
+ const transactions = await ExpoIapModule.getAllTransactionsIOS();
+ return (transactions ?? []) as PurchaseIOS[];
+};
+
/**
* Clear a specific transaction (iOS only).
*
diff --git a/libraries/flutter_inapp_purchase/ios/Classes/FlutterInappPurchasePlugin.swift b/libraries/flutter_inapp_purchase/ios/Classes/FlutterInappPurchasePlugin.swift
index 1057813f..bbcef3da 100644
--- a/libraries/flutter_inapp_purchase/ios/Classes/FlutterInappPurchasePlugin.swift
+++ b/libraries/flutter_inapp_purchase/ios/Classes/FlutterInappPurchasePlugin.swift
@@ -142,6 +142,9 @@ public class FlutterInappPurchasePlugin: NSObject, FlutterPlugin {
case "getPendingTransactionsIOS":
getPendingTransactionsIOS(result: result)
+ case "getAllTransactionsIOS":
+ getAllTransactionsIOS(result: result)
+
case "requestPurchaseOnPromotedProductIOS":
requestPurchaseOnPromotedProductIOS(result: result)
@@ -663,6 +666,23 @@ public class FlutterInappPurchasePlugin: NSObject, FlutterPlugin {
}
}
+ private func getAllTransactionsIOS(result: @escaping FlutterResult) {
+ Task { @MainActor in
+ do {
+ let all = try await OpenIapModule.shared.getAllTransactionsIOS()
+ let purchases = all.map { Purchase.purchaseIos($0) }
+ let serialized = FlutterIapHelper.sanitizeArray(OpenIapSerialization.purchases(purchases))
+ FlutterIapLog.result("getAllTransactionsIOS", value: serialized)
+ result(serialized)
+ } catch {
+ await MainActor.run {
+ let code: ErrorCode = .serviceError
+ result(FlutterError(code: code.rawValue, message: defaultMessage(for: code), details: nil))
+ }
+ }
+ }
+ }
+
private func clearTransactionIOS(result: @escaping FlutterResult) {
FlutterIapLog.debug("clearTransactionIOS called")
Task { @MainActor in
diff --git a/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart b/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
index f0c5f690..1200f520 100644
--- a/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
+++ b/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
@@ -964,6 +964,26 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
return const [];
};
+ gentype.QueryGetAllTransactionsIOSHandler get getAllTransactionsIOS =>
+ () async {
+ if (_platform.isIOS || _platform.isMacOS) {
+ final dynamic result = await _channel.invokeMethod(
+ 'getAllTransactionsIOS',
+ );
+ final purchases = extractPurchases(
+ result,
+ platformIsAndroid: _platform.isAndroid,
+ platformIsIOS: _platform.isIOS || _platform.isMacOS,
+ acknowledgedAndroidPurchaseTokens:
+ _acknowledgedAndroidPurchaseTokens,
+ );
+ return purchases.whereType().toList(
+ growable: false,
+ );
+ }
+ return const [];
+ };
+
gentype.MutationAcknowledgePurchaseAndroidHandler
get acknowledgePurchaseAndroid => (purchaseToken) async {
if (!_platform.isAndroid) {
@@ -2254,6 +2274,7 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
getAvailablePurchases: getAvailablePurchases,
getExternalPurchaseCustomLinkTokenIOS:
getExternalPurchaseCustomLinkTokenIOS,
+ getAllTransactionsIOS: getAllTransactionsIOS,
getPendingTransactionsIOS: getPendingTransactionsIOS,
getPromotedProductIOS: getPromotedProductIOS,
getStorefront: getStorefront,
diff --git a/libraries/godot-iap/addons/godot-iap/godot_iap.gd b/libraries/godot-iap/addons/godot-iap/godot_iap.gd
index 7f1fb6c1..e0bb9c57 100644
--- a/libraries/godot-iap/addons/godot-iap/godot_iap.gd
+++ b/libraries/godot-iap/addons/godot-iap/godot_iap.gd
@@ -641,6 +641,23 @@ func get_pending_transactions_ios() -> Array:
purchases.append(Types.PurchaseIOS.from_dict(tx))
return purchases
+## Get all transactions including finished consumables (iOS only).
+## Requires SK2ConsumableTransactionHistory Info.plist key for finished consumables (iOS 18+).
+## @return Array of Types.PurchaseIOS
+func get_all_transactions_ios() -> Array:
+ var purchases: Array = []
+ if _native_plugin and _platform == "iOS":
+ var result_json = _native_plugin.call("getAllTransactionsIOS")
+ var result = JSON.parse_string(result_json)
+ if result is Dictionary and result.get("success", false):
+ var transactions_json = result.get("transactionsJson", "[]")
+ var transactions = JSON.parse_string(transactions_json)
+ if transactions is Array:
+ for tx in transactions:
+ if tx is Dictionary:
+ purchases.append(Types.PurchaseIOS.from_dict(tx))
+ return purchases
+
## Present code redemption sheet (iOS only).
## @return Types.VoidResult
func present_code_redemption_sheet_ios() -> Variant:
diff --git a/libraries/godot-iap/ios-gdextension/Sources/GodotIap/GodotIap.swift b/libraries/godot-iap/ios-gdextension/Sources/GodotIap/GodotIap.swift
index 15d9e426..ee5174ac 100644
--- a/libraries/godot-iap/ios-gdextension/Sources/GodotIap/GodotIap.swift
+++ b/libraries/godot-iap/ios-gdextension/Sources/GodotIap/GodotIap.swift
@@ -483,6 +483,33 @@ public class GodotIap: RefCounted, @unchecked Sendable {
return "{\"status\": \"pending\"}"
}
+ @Callable
+ public func getAllTransactionsIOS() -> String {
+ GodotIapLog.payload("Getting all transactions", payload: nil)
+
+ Task { [weak self] in
+ guard let self = self else { return }
+ do {
+ let transactions = try await self.openIap.getAllTransactionsIOS()
+ let transactionDicts = transactions.map { self.purchaseIOSToDictionary($0) }
+
+ if let jsonData = try? JSONSerialization.data(withJSONObject: transactionDicts),
+ let jsonString = String(data: jsonData, encoding: .utf8) {
+ await MainActor.run { [self] in
+ let dict = VariantDictionary()
+ dict["success"] = Variant(true)
+ dict["transactionsJson"] = Variant(jsonString)
+ self.productsFetched.emit(dict)
+ }
+ }
+ } catch {
+ GodotIapLog.debug("[GodotIap] getAllTransactionsIOS error: \(error.localizedDescription)")
+ }
+ }
+
+ return "{\"status\": \"pending\"}"
+ }
+
@Callable
public func presentCodeRedemptionSheetIOS() -> String {
GodotIapLog.payload("Presenting code redemption sheet", payload: nil)
diff --git a/libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt b/libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt
index ee38ea48..34428bae 100644
--- a/libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt
+++ b/libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt
@@ -1546,6 +1546,12 @@ class HybridRnIap : HybridRnIapSpec() {
}
}
+ override fun getAllTransactionsIOS(): Promise> {
+ return Promise.async {
+ throw OpenIapException(toErrorJson(OpenIAPError.FeatureNotSupported()))
+ }
+ }
+
override fun syncIOS(): Promise {
return Promise.async {
throw OpenIapException(toErrorJson(OpenIAPError.FeatureNotSupported()))
diff --git a/libraries/react-native-iap/ios/HybridRnIap.swift b/libraries/react-native-iap/ios/HybridRnIap.swift
index 36c9b10f..a1677c22 100644
--- a/libraries/react-native-iap/ios/HybridRnIap.swift
+++ b/libraries/react-native-iap/ios/HybridRnIap.swift
@@ -717,6 +717,39 @@ class HybridRnIap: HybridRnIapSpec {
}
}
+ func getAllTransactionsIOS() throws -> Promise<[NitroPurchase]> {
+ return Promise.async {
+ do {
+ RnIapLog.payload("getAllTransactionsIOS", nil)
+ let all = try await OpenIapModule.shared.getAllTransactionsIOS()
+ var unionPurchases: [OpenIAP.Purchase] = []
+ var payloadUpdates: [String: [String: Any]] = [:]
+ for purchase in all {
+ let union = OpenIAP.Purchase.purchaseIos(purchase)
+ unionPurchases.append(union)
+ let raw = OpenIapSerialization.purchase(union)
+ if let identifier = raw["id"] as? String {
+ payloadUpdates[identifier] = raw
+ }
+ }
+ await MainActor.run {
+ for (key, value) in payloadUpdates {
+ self.purchasePayloadById[key] = value
+ }
+ }
+ let payloads = RnIapHelper.sanitizeArray(OpenIapSerialization.purchases(unionPurchases))
+ RnIapLog.result("getAllTransactionsIOS", payloads)
+ return payloads.map { RnIapHelper.convertPurchaseDictionary($0) }
+ } catch let purchaseError as PurchaseError {
+ RnIapLog.failure("getAllTransactionsIOS", error: purchaseError)
+ throw OpenIapException(purchaseError.toJsonString())
+ } catch {
+ RnIapLog.failure("getAllTransactionsIOS", error: error)
+ throw OpenIapException(toErrorJson(OpenIAPError.ServiceError(debugMessage: error.localizedDescription)))
+ }
+ }
+ }
+
func syncIOS() throws -> Promise {
return Promise.async {
do {
diff --git a/libraries/react-native-iap/src/__tests__/index.test.ts b/libraries/react-native-iap/src/__tests__/index.test.ts
index cad3ebeb..8771602c 100644
--- a/libraries/react-native-iap/src/__tests__/index.test.ts
+++ b/libraries/react-native-iap/src/__tests__/index.test.ts
@@ -38,6 +38,7 @@ const mockIap: any = {
requestPromotedProductIOS: jest.fn(async () => null),
buyPromotedProductIOS: jest.fn(async () => undefined),
presentCodeRedemptionSheetIOS: jest.fn(async () => true),
+ getAllTransactionsIOS: jest.fn(async () => []),
// Unified storefront
getStorefront: jest.fn(async () => 'USA'),
diff --git a/libraries/react-native-iap/src/index.ts b/libraries/react-native-iap/src/index.ts
index fe7a8e06..c5fc07dc 100644
--- a/libraries/react-native-iap/src/index.ts
+++ b/libraries/react-native-iap/src/index.ts
@@ -1080,6 +1080,32 @@ export const getPendingTransactionsIOS: QueryField<
}
};
+export const getAllTransactionsIOS: QueryField<
+ 'getAllTransactionsIOS'
+> = async () => {
+ if (Platform.OS !== 'ios') {
+ return [];
+ }
+
+ try {
+ const nitroPurchases = await IAP.instance.getAllTransactionsIOS();
+ return nitroPurchases
+ .map(convertNitroPurchaseToPurchase)
+ .filter(
+ (purchase): purchase is PurchaseIOS => purchase.platform === 'ios',
+ );
+ } catch (error) {
+ RnIapConsole.error('[getAllTransactionsIOS] Failed:', error);
+ const parsedError = parseErrorStringToJsonObj(error);
+ throw createPurchaseError({
+ code: parsedError.code,
+ message: parsedError.message,
+ responseCode: parsedError.responseCode,
+ debugMessage: parsedError.debugMessage,
+ });
+ }
+};
+
export const showManageSubscriptionsIOS: MutationField<
'showManageSubscriptionsIOS'
> = async () => {
diff --git a/libraries/react-native-iap/src/specs/RnIap.nitro.ts b/libraries/react-native-iap/src/specs/RnIap.nitro.ts
index 2c90288f..94643735 100644
--- a/libraries/react-native-iap/src/specs/RnIap.nitro.ts
+++ b/libraries/react-native-iap/src/specs/RnIap.nitro.ts
@@ -857,6 +857,14 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
*/
getPendingTransactionsIOS(): Promise;
+ /**
+ * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * Requires SK2ConsumableTransactionHistory Info.plist key for finished consumables (iOS 18+).
+ * @returns Promise - Array of all transactions
+ * @platform iOS
+ */
+ getAllTransactionsIOS(): Promise;
+
/**
* Sync with the App Store (iOS only)
* @returns Promise - Success flag
diff --git a/packages/docs/src/pages/docs/foundation/founding-supporters.tsx b/packages/docs/src/pages/docs/foundation/founding-supporters.tsx
index 78001aed..7b458b69 100644
--- a/packages/docs/src/pages/docs/foundation/founding-supporters.tsx
+++ b/packages/docs/src/pages/docs/foundation/founding-supporters.tsx
@@ -15,6 +15,21 @@ function FoundingSupporters() {
keywords="OpenIAP founding supporter, open source sponsor, IAP standard supporter"
/>
Become a Founding Supporter
+
+ Draft — The Foundation section is currently being
+ prepared. Content may change as the governance structure is finalized.
+
We're building OpenIAP into a vendor-neutral, open standard for in-app
purchases — and we're looking for organizations to join as Founding
diff --git a/packages/docs/src/pages/docs/foundation/governance.tsx b/packages/docs/src/pages/docs/foundation/governance.tsx
index f59b2555..33420104 100644
--- a/packages/docs/src/pages/docs/foundation/governance.tsx
+++ b/packages/docs/src/pages/docs/foundation/governance.tsx
@@ -14,6 +14,21 @@ function Governance() {
keywords="OpenIAP governance, open source governance, TSC, technical steering committee, maintainer policy"
/>
Project Governance
+
+ Draft — The Foundation section is currently being
+ prepared. Content may change as the governance structure is finalized.
+
OpenIAP is an open-source project providing a neutral interoperability
standard for in-app purchase APIs and verification across platforms.
diff --git a/packages/docs/src/pages/docs/foundation/one-pager.tsx b/packages/docs/src/pages/docs/foundation/one-pager.tsx
index 40c01cdd..9ef12f75 100644
--- a/packages/docs/src/pages/docs/foundation/one-pager.tsx
+++ b/packages/docs/src/pages/docs/foundation/one-pager.tsx
@@ -17,6 +17,21 @@ function OnePager() {
OpenIAP: Neutral Interoperability Layer for In-App Purchase APIs and
Verification
+
+ Draft — The Foundation section is currently being
+ prepared. Content may change as the governance structure is finalized.
+
@@ -27,7 +42,85 @@ function OnePager() {
Every framework — React Native, Expo, Flutter, KMP, Godot, native iOS,
native Android — reinvents the same wheel: different type definitions,
different error models, different verification flows, different
- edge-case handling. This leads to:
+ edge-case handling.
+
+
+ The landscape is expanding rapidly. New platforms like{' '}
+
+ Meta Horizon OS
+
+ ,{' '}
+
+ Vega OS
+
+ ,{' '}
+
+ HarmonyOS
+
+ , and{' '}
+
+ Amazon Fire OS
+ {' '}
+ continue to emerge and grow, while stores beyond Google Play and the
+ App Store — such as{' '}
+
+ Galaxy Store
+
+ ,{' '}
+
+ Huawei AppGallery
+
+ , and alternative marketplaces like{' '}
+
+ Onside
+ {' '}
+ — each bring their own billing APIs. Even the established stores like{' '}
+
+ Google Play
+ {' '}
+ and{' '}
+
+ Apple App Store
+ {' '}
+ evolve their billing APIs with every major release. As this
+ fragmentation accelerates with every new platform and marketplace, a
+ unified standard becomes not just useful but essential. This leads to:
-
@@ -43,8 +136,8 @@ function OnePager() {
prevention are left as afterthoughts
-
- High maintenance burden as Apple and Google
- frequently change their billing APIs
+ High maintenance burden as Apple, Google, and an
+ expanding set of stores frequently change their billing APIs
diff --git a/packages/docs/src/pages/docs/foundation/roadmap-budget.tsx b/packages/docs/src/pages/docs/foundation/roadmap-budget.tsx
index 0a6da038..4c04ab29 100644
--- a/packages/docs/src/pages/docs/foundation/roadmap-budget.tsx
+++ b/packages/docs/src/pages/docs/foundation/roadmap-budget.tsx
@@ -14,6 +14,21 @@ function RoadmapBudget() {
keywords="OpenIAP roadmap, funding plan, open source budget, IAP development roadmap"
/>
Roadmap & Budget
+
+ Draft — The Foundation section is currently being
+ prepared. Content may change as the governance structure is finalized.
+
This document outlines how OpenIAP plans to grow and how sponsorship
funding is allocated. Full transparency on where every dollar goes.
@@ -263,7 +278,7 @@ function RoadmapBudget() {
| Domain registration |
- ~$2 |
+ ~$3 |
openiap.dev annual amortized |
@@ -281,12 +296,22 @@ function RoadmapBudget() {
| ~$2 |
$25 one-time amortized |
+
+ | Claude Code (AI assistant) |
+ $200 |
+ Anthropic Max plan for development |
+
+
+ | Codex (AI assistant) |
+ $100 |
+ OpenAI for code review and testing |
+
|
Total baseline
|
- ~$80/month
+ $330–380/month
|
Excluding maintainer time |
diff --git a/packages/docs/src/pages/docs/foundation/sponsorship.tsx b/packages/docs/src/pages/docs/foundation/sponsorship.tsx
index 1b972c91..7dc1c6f0 100644
--- a/packages/docs/src/pages/docs/foundation/sponsorship.tsx
+++ b/packages/docs/src/pages/docs/foundation/sponsorship.tsx
@@ -15,6 +15,21 @@ function Sponsorship() {
keywords="OpenIAP sponsorship, open source funding, IAP sponsor, founding supporter"
/>
Sponsorship
+
+ Draft — The Foundation section is currently being
+ prepared. Content may change as the governance structure is finalized.
+
OpenIAP is the open interoperability standard for in-app purchases. Your
sponsorship directly funds the infrastructure, security, and
diff --git a/packages/docs/src/pages/docs/updates/releases.tsx b/packages/docs/src/pages/docs/updates/releases.tsx
index 98a18152..3d4327b8 100644
--- a/packages/docs/src/pages/docs/updates/releases.tsx
+++ b/packages/docs/src/pages/docs/updates/releases.tsx
@@ -152,6 +152,51 @@ function Releases() {
openiap-apple 2.1.2
+
+
+ react-native-iap 15.2.1
+
+
+
+
+ expo-iap 4.2.1
+
+
+
+
+ flutter_inapp_purchase 9.2.1
+
+
+
+
+ kmp-iap 2.2.1
+
+
+
+
+ godot-iap 2.2.1
+
+
diff --git a/packages/docs/src/pages/docs/updates/versions.tsx b/packages/docs/src/pages/docs/updates/versions.tsx
index d21ff6de..fd0ffcb7 100644
--- a/packages/docs/src/pages/docs/updates/versions.tsx
+++ b/packages/docs/src/pages/docs/updates/versions.tsx
@@ -8,7 +8,7 @@ const GOOGLE_MAVEN_BADGE =
const GOOGLE_MAVEN_ARTIFACT =
'https://central.sonatype.com/artifact/io.github.hyochan.openiap/openiap-google';
const APPLE_SWIFT_BADGE =
- 'https://img.shields.io/github/v/tag/hyodotdev/openiap?filter=apple-v*&label=Swift%20Package&logo=swift&color=orange';
+ 'https://img.shields.io/github/v/tag/hyodotdev/openiap?filter=2.*&label=Swift%20Package&logo=swift&color=orange';
const APPLE_SWIFT_URL =
'https://github.com/hyodotdev/openiap/tree/main/packages/apple';
const APPLE_COCOAPODS_BADGE =
@@ -153,24 +153,15 @@ function Versions() {
href={latestGqlRelease.pageUrl}
target="_blank"
rel="noopener noreferrer"
- className="btn btn-secondary"
+ className="btn btn-secondary no-icon"
>
- Latest tag: {latestGqlRelease.tag}
+ Latest tag: {latestGqlRelease.tag} ↗
View all releases
diff --git a/packages/docs/src/styles/documentation.css b/packages/docs/src/styles/documentation.css
index 3107a654..68fb652d 100644
--- a/packages/docs/src/styles/documentation.css
+++ b/packages/docs/src/styles/documentation.css
@@ -553,20 +553,20 @@
}
/* Documentation Links - Oatmeal Colors */
-.doc-page a:not(.anchor-link) {
+.doc-page a:not(.anchor-link, .btn) {
color: #8b6545; /* Warm brown */
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color 0.2s ease;
}
-.doc-page a:not(.anchor-link):hover {
+.doc-page a:not(.anchor-link, .btn):hover {
border-bottom-color: #d4a574; /* Light oatmeal */
}
/* External links with icon */
.doc-page a.external-link,
-.doc-page a[target='_blank'] {
+.doc-page a[target='_blank']:not(.btn) {
color: #8b6545;
text-decoration: none;
border-bottom: 1px dotted #d4a574;
@@ -577,13 +577,13 @@
}
.doc-page a.external-link:hover,
-.doc-page a[target='_blank']:hover {
+.doc-page a[target='_blank']:not(.btn):hover {
color: var(--primary-dark);
border-bottom-style: solid;
}
.doc-page a.external-link::after,
-.doc-page a[target='_blank']:not(.no-icon)::after {
+.doc-page a[target='_blank']:not(.no-icon, .btn)::after {
content: '↗';
font-size: 0.75em;
opacity: 0.7;
@@ -591,7 +591,7 @@
}
.doc-page a.external-link:hover::after,
-.doc-page a[target='_blank']:hover::after {
+.doc-page a[target='_blank']:not(.btn):hover::after {
transform: translate(2px, -2px);
opacity: 1;
}
@@ -639,23 +639,23 @@
}
/* Dark mode adjustments for links - Oatmeal theme */
-:root.dark .doc-page a:not(.anchor-link) {
+:root.dark .doc-page a:not(.anchor-link, .btn) {
color: #d4a574;
}
-:root.dark .doc-page a:not(.anchor-link):hover {
+:root.dark .doc-page a:not(.anchor-link, .btn):hover {
color: #e6c299;
border-bottom-color: #d4a574;
}
:root.dark .doc-page a.external-link,
-:root.dark .doc-page a[target='_blank'] {
+:root.dark .doc-page a[target='_blank']:not(.btn) {
color: #d4a574;
border-bottom-color: rgba(212, 165, 116, 0.3);
}
:root.dark .doc-page a.external-link:hover,
-:root.dark .doc-page a[target='_blank']:hover {
+:root.dark .doc-page a[target='_blank']:not(.btn):hover {
color: #e6c299;
border-bottom-color: rgba(212, 165, 116, 0.6);
}